diff --git a/.travis.yml b/.travis.yml index b1701e4a65451..0646f4d4687a6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -301,7 +301,7 @@ after_failure: EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!checkout!\(.*\)|\1|;y|!|/|'); if [ -f "$EXE" ]; then printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE"; - gdb -q -c "$CORE" "$EXE" + gdb --batch -q -c "$CORE" "$EXE" -iex 'set auto-load off' -iex 'dir src/' -iex 'set sysroot .' diff --git a/src/doc/book b/src/doc/book index cff0930664b68..fa91738b66367 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit cff0930664b688f1dd22aefb3d16944eb4cdbfd5 +Subproject commit fa91738b66367b6f70b078251868a071f1991ace diff --git a/src/libcore/time.rs b/src/libcore/time.rs index b58920224eb70..1aed5a7b426fd 100644 --- a/src/libcore/time.rs +++ b/src/libcore/time.rs @@ -21,7 +21,7 @@ //! assert_eq!(Duration::new(5, 0), Duration::from_secs(5)); //! ``` -use fmt; +use {fmt, u64}; use iter::Sum; use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; @@ -30,6 +30,7 @@ const NANOS_PER_MILLI: u32 = 1_000_000; const NANOS_PER_MICRO: u32 = 1_000; const MILLIS_PER_SEC: u64 = 1_000; const MICROS_PER_SEC: u64 = 1_000_000; +const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f64; /// A `Duration` type to represent a span of time, typically used for system /// timeouts. @@ -458,6 +459,115 @@ impl Duration { None } } + + /// Returns the number of seconds contained by this `Duration` as `f64`. + /// + /// The returned value does include the fractional (nanosecond) part of the duration. + /// + /// # Examples + /// ``` + /// #![feature(duration_float)] + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 700_000_000); + /// assert_eq!(dur.as_float_secs(), 2.7); + /// ``` + #[unstable(feature = "duration_float", issue = "54361")] + #[inline] + pub fn as_float_secs(&self) -> f64 { + (self.secs as f64) + (self.nanos as f64) / (NANOS_PER_SEC as f64) + } + + /// Creates a new `Duration` from the specified number of seconds. + /// + /// # Panics + /// This constructor will panic if `secs` is not finite, negative or overflows `Duration`. + /// + /// # Examples + /// ``` + /// #![feature(duration_float)] + /// use std::time::Duration; + /// + /// let dur = Duration::from_float_secs(2.7); + /// assert_eq!(dur, Duration::new(2, 700_000_000)); + /// ``` + #[unstable(feature = "duration_float", issue = "54361")] + #[inline] + pub fn from_float_secs(secs: f64) -> Duration { + let nanos = secs * (NANOS_PER_SEC as f64); + if !nanos.is_finite() { + panic!("got non-finite value when converting float to duration"); + } + if nanos >= MAX_NANOS_F64 { + panic!("overflow when converting float to duration"); + } + if nanos < 0.0 { + panic!("underflow when converting float to duration"); + } + let nanos = nanos as u128; + Duration { + secs: (nanos / (NANOS_PER_SEC as u128)) as u64, + nanos: (nanos % (NANOS_PER_SEC as u128)) as u32, + } + } + + /// Multiply `Duration` by `f64`. + /// + /// # Panics + /// This method will panic if result is not finite, negative or overflows `Duration`. + /// + /// # Examples + /// ``` + /// #![feature(duration_float)] + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 700_000_000); + /// assert_eq!(dur.mul_f64(3.14), Duration::new(8, 478_000_000)); + /// assert_eq!(dur.mul_f64(3.14e5), Duration::new(847_800, 0)); + /// ``` + #[unstable(feature = "duration_float", issue = "54361")] + #[inline] + pub fn mul_f64(self, rhs: f64) -> Duration { + Duration::from_float_secs(rhs * self.as_float_secs()) + } + + /// Divide `Duration` by `f64`. + /// + /// # Panics + /// This method will panic if result is not finite, negative or overflows `Duration`. + /// + /// # Examples + /// ``` + /// #![feature(duration_float)] + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 700_000_000); + /// assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611)); + /// // note that truncation is used, not rounding + /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_598)); + /// ``` + #[unstable(feature = "duration_float", issue = "54361")] + #[inline] + pub fn div_f64(self, rhs: f64) -> Duration { + Duration::from_float_secs(self.as_float_secs() / rhs) + } + + /// Divide `Duration` by `Duration` and return `f64`. + /// + /// # Examples + /// ``` + /// #![feature(duration_float)] + /// use std::time::Duration; + /// + /// let dur1 = Duration::new(2, 700_000_000); + /// let dur2 = Duration::new(5, 400_000_000); + /// assert_eq!(dur1.div_duration(dur2), 0.5); + /// ``` + #[unstable(feature = "duration_float", issue = "54361")] + #[inline] + pub fn div_duration(self, rhs: Duration) -> f64 { + self.as_float_secs() / rhs.as_float_secs() + } } #[stable(feature = "duration", since = "1.3.0")] @@ -501,6 +611,15 @@ impl Mul for Duration { } } +#[stable(feature = "symmetric_u32_duration_mul", since = "1.31.0")] +impl Mul for u32 { + type Output = Duration; + + fn mul(self, rhs: Duration) -> Duration { + rhs * self + } +} + #[stable(feature = "time_augmented_assignment", since = "1.9.0")] impl MulAssign for Duration { fn mul_assign(&mut self, rhs: u32) { diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index ed95aa73078a9..4bed3c5935cd7 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -112,6 +112,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { orig_params, trait_pred.to_poly_trait_predicate(), )); + match result { Ok(Some(Vtable::VtableImpl(_))) => { debug!( @@ -119,10 +120,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { manual impl found, bailing out", did, trait_did, generics ); - return true; + true } - _ => return false, - }; + _ => false + } }); // If an explicit impl exists, it always takes priority over an auto impl @@ -426,6 +427,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { if new_trait.def_id() == old_trait.def_id() { let new_substs = new_trait.skip_binder().trait_ref.substs; let old_substs = old_trait.skip_binder().trait_ref.substs; + if !new_substs.types().eq(old_substs.types()) { // We can't compare lifetimes if the types are different, // so skip checking old_pred @@ -489,12 +491,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { pub fn get_lifetime(&self, region: Region, names_map: &FxHashMap) -> String { self.region_name(region) - .map(|name| { - names_map.get(&name).unwrap_or_else(|| { + .map(|name| + names_map.get(&name).unwrap_or_else(|| panic!("Missing lifetime with name {:?} for {:?}", name, region) - }) - }) - .unwrap_or(&"'static".to_string()) + ) + ) + .unwrap_or(&"'static".to_owned()) .clone() } diff --git a/src/librustc/traits/codegen/mod.rs b/src/librustc/traits/codegen/mod.rs index cf404202ac120..4e88150a18acc 100644 --- a/src/librustc/traits/codegen/mod.rs +++ b/src/librustc/traits/codegen/mod.rs @@ -39,7 +39,7 @@ pub fn codegen_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>, let trait_ref = ty.erase_regions(&trait_ref); debug!("codegen_fulfill_obligation(trait_ref={:?}, def_id={:?})", - (param_env, trait_ref), trait_ref.def_id()); + (param_env, trait_ref), trait_ref.def_id()); // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. @@ -48,8 +48,8 @@ pub fn codegen_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>, let obligation_cause = ObligationCause::dummy(); let obligation = Obligation::new(obligation_cause, - param_env, - trait_ref.to_poly_trait_predicate()); + param_env, + trait_ref.to_poly_trait_predicate()); let selection = match selcx.select(&obligation) { Ok(Some(selection)) => selection, @@ -61,12 +61,11 @@ pub fn codegen_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>, // overflow bug, since I believe this is the only case // where ambiguity can result. bug!("Encountered ambiguity selecting `{:?}` during codegen, \ - presuming due to overflow", - trait_ref) + presuming due to overflow", + trait_ref) } Err(e) => { - bug!("Encountered error `{:?}` selecting `{:?}` during codegen", - e, trait_ref) + bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref) } }; @@ -163,22 +162,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // In principle, we only need to do this so long as `result` // contains unbound type parameters. It could be a slight // optimization to stop iterating early. - match fulfill_cx.select_all_or_error(self) { - Ok(()) => { } - Err(errors) => { - span_bug!(span, "Encountered errors `{:?}` resolving bounds after type-checking", - errors); - } + if let Err(errors) = fulfill_cx.select_all_or_error(self) { + span_bug!(span, "Encountered errors `{:?}` resolving bounds after type-checking", + errors); } let result = self.resolve_type_vars_if_possible(result); let result = self.tcx.erase_regions(&result); - match self.tcx.lift_to_global(&result) { - Some(result) => result, - None => { - span_bug!(span, "Uninferred types/regions in `{:?}`", result); - } - } + self.tcx.lift_to_global(&result).unwrap_or_else(|| + span_bug!(span, "Uninferred types/regions in `{:?}`", result) + ) } } diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index b8dd2a12fb58d..251743b0d3bb4 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -115,9 +115,7 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, b_def_id: DefId) -> Option> { - debug!("overlap(a_def_id={:?}, b_def_id={:?})", - a_def_id, - b_def_id); + debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id); // For the purposes of this check, we don't bring any skolemized // types into scope; instead, we replace the generic types with @@ -133,10 +131,9 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, // Do `a` and `b` unify? If not, no overlap. let obligations = match selcx.infcx().at(&ObligationCause::dummy(), param_env) - .eq_impl_headers(&a_impl_header, &b_impl_header) { - Ok(InferOk { obligations, value: () }) => { - obligations - } + .eq_impl_headers(&a_impl_header, &b_impl_header) + { + Ok(InferOk { obligations, value: () }) => obligations, Err(_) => return None }; @@ -164,7 +161,7 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, return None } - let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header); + let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header); let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes(); debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes); Some(OverlapResult { impl_header, intercrate_ambiguity_causes }) @@ -471,14 +468,12 @@ fn ty_is_local_constructor(ty: Ty, in_crate: InCrate) -> bool { ty::Foreign(did) => def_id_is_local(did, in_crate), ty::Dynamic(ref tt, ..) => { - tt.principal().map_or(false, |p| { + tt.principal().map_or(false, |p| def_id_is_local(p.def_id(), in_crate) - }) + ) } - ty::Error => { - true - } + ty::Error => true, ty::Closure(..) | ty::Generator(..) | diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 466d472cca338..6fb5acde72c49 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -34,6 +34,7 @@ use hir::def_id::DefId; use infer::{self, InferCtxt}; use infer::type_variable::TypeVariableOrigin; use std::fmt; +use std::iter; use syntax::ast; use session::DiagnosticMessageId; use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; @@ -58,7 +59,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { index: Option, // None if this is an old error } - let mut error_map : FxHashMap<_, Vec<_>> = + let mut error_map: FxHashMap<_, Vec<_>> = self.reported_trait_errors.borrow().iter().map(|(&span, predicates)| { (span, predicates.iter().map(|predicate| ErrorDescriptor { predicate: predicate.clone(), @@ -80,7 +81,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // We do this in 2 passes because we want to display errors in order, tho // maybe it *is* better to sort errors by span or something. - let mut is_suppressed: Vec = errors.iter().map(|_| false).collect(); + let mut is_suppressed = vec![false; errors.len()]; for (_, error_set) in error_map.iter() { // We want to suppress "duplicate" errors with the same span. for error in error_set { @@ -349,7 +350,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { _ => { // this is a "direct", user-specified, rather than derived, // obligation. - flags.push(("direct".to_string(), None)); + flags.push(("direct".to_owned(), None)); } } @@ -361,24 +362,24 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Currently I'm leaving it for what I need for `try`. if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) { let method = self.tcx.item_name(item); - flags.push(("from_method".to_string(), None)); - flags.push(("from_method".to_string(), Some(method.to_string()))); + flags.push(("from_method".to_owned(), None)); + flags.push(("from_method".to_owned(), Some(method.to_string()))); } } if let Some(k) = obligation.cause.span.compiler_desugaring_kind() { - flags.push(("from_desugaring".to_string(), None)); - flags.push(("from_desugaring".to_string(), Some(k.name().to_string()))); + flags.push(("from_desugaring".to_owned(), None)); + flags.push(("from_desugaring".to_owned(), Some(k.name().to_string()))); } let generics = self.tcx.generics_of(def_id); let self_ty = trait_ref.self_ty(); // This is also included through the generics list as `Self`, // but the parser won't allow you to use it - flags.push(("_Self".to_string(), Some(self_ty.to_string()))); + flags.push(("_Self".to_owned(), Some(self_ty.to_string()))); if let Some(def) = self_ty.ty_adt_def() { // We also want to be able to select self's original // signature with no type arguments resolved - flags.push(("_Self".to_string(), Some(self.tcx.type_of(def.did).to_string()))); + flags.push(("_Self".to_owned(), Some(self.tcx.type_of(def.did).to_string()))); } for param in generics.params.iter() { @@ -393,7 +394,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) { - flags.push(("crate_local".to_string(), None)); + flags.push(("crate_local".to_owned(), None)); } if let Ok(Some(command)) = OnUnimplementedDirective::of_item( @@ -412,27 +413,26 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true); - let mut impl_candidates = Vec::new(); + let all_impls = self.tcx.all_impls(trait_ref.def_id()); match simp { - Some(simp) => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| { + Some(simp) => all_impls.iter().filter_map(|&def_id| { let imp = self.tcx.impl_trait_ref(def_id).unwrap(); let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true); if let Some(imp_simp) = imp_simp { if simp != imp_simp { - return; + return None } } - impl_candidates.push(imp); - }), - None => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| { - impl_candidates.push( - self.tcx.impl_trait_ref(def_id).unwrap()); - }) - }; - impl_candidates + + Some(imp) + }).collect(), + None => all_impls.iter().map(|&def_id| + self.tcx.impl_trait_ref(def_id).unwrap() + ).collect() + } } fn report_similar_impl_candidates(&self, @@ -603,10 +603,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { span, E0277, "{}", - message.unwrap_or_else(|| { + message.unwrap_or_else(|| format!("the trait bound `{}` is not satisfied{}", trait_ref.to_predicate(), post_message) - })); + )); let explanation = if obligation.cause.code == ObligationCauseCode::MainFunctionType { @@ -645,7 +645,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // "the type `T` can't be frobnicated" // which is somewhat confusing. err.help(&format!("consider adding a `where {}` bound", - trait_ref.to_predicate())); + trait_ref.to_predicate())); } else if !have_alt_message { // Can't show anything else useful, try to find similar impls. let impl_candidates = self.find_similar_impl_candidates(trait_ref); @@ -693,7 +693,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::Predicate::RegionOutlives(ref predicate) => { let predicate = self.resolve_type_vars_if_possible(predicate); let err = self.region_outlives_predicate(&obligation.cause, - &predicate).err().unwrap(); + &predicate).err().unwrap(); struct_span_err!(self.tcx.sess, span, E0279, "the requirement `{}` is not satisfied (`{}`)", predicate, err) @@ -722,7 +722,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let mut err = struct_span_err!( self.tcx.sess, closure_span, E0525, "expected a closure that implements the `{}` trait, \ - but this closure only implements `{}`", + but this closure only implements `{}`", kind, found_kind); @@ -779,40 +779,34 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => { let found_trait_ref = self.resolve_type_vars_if_possible(&*found_trait_ref); let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref); + if expected_trait_ref.self_ty().references_error() { return; } + let found_trait_ty = found_trait_ref.self_ty(); let found_did = match found_trait_ty.sty { - ty::Closure(did, _) | - ty::Foreign(did) | - ty::FnDef(did, _) => Some(did), + ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did), ty::Adt(def, _) => Some(def.did), _ => None, }; - let found_span = found_did.and_then(|did| { + + let found_span = found_did.and_then(|did| self.tcx.hir.span_if_local(did) - }).map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def + ).map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def let found = match found_trait_ref.skip_binder().substs.type_at(1).sty { - ty::Tuple(ref tys) => tys.iter() - .map(|_| ArgKind::empty()).collect::>(), + ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()], _ => vec![ArgKind::empty()], }; + let expected = match expected_trait_ref.skip_binder().substs.type_at(1).sty { ty::Tuple(ref tys) => tys.iter() - .map(|t| match t.sty { - ty::Tuple(ref tys) => ArgKind::Tuple( - Some(span), - tys.iter() - .map(|ty| ("_".to_owned(), ty.sty.to_string())) - .collect::>() - ), - _ => ArgKind::Arg("_".to_owned(), t.sty.to_string()), - }).collect(), + .map(|t| ArgKind::from_expected_ty(t, Some(span))).collect(), ref sty => vec![ArgKind::Arg("_".to_owned(), sty.to_string())], }; + if found.len() == expected.len() { self.report_closure_arg_mismatch(span, found_span, @@ -836,8 +830,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { TraitNotObjectSafe(did) => { let violations = self.tcx.object_safety_violations(did); - self.tcx.report_object_safety_error(span, did, - violations) + self.tcx.report_object_safety_error(span, did, violations) } ConstEvalFailure(ref err) => { @@ -846,7 +839,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { "could not evaluate constant expression", ) { Some(err) => err, - None => return, + None => { + self.tcx.sess.delay_span_bug(span, + &format!("constant in type had an ignored error: {:?}", err)); + return; + } } } @@ -981,11 +978,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .map(|arg| match arg.clone().node { hir::TyKind::Tup(ref tys) => ArgKind::Tuple( Some(arg.span), - tys.iter() - .map(|_| ("_".to_owned(), "_".to_owned())) - .collect::>(), + vec![("_".to_owned(), "_".to_owned()); tys.len()] ), - _ => ArgKind::Arg("_".to_owned(), "_".to_owned()) + _ => ArgKind::empty() }).collect::>()) } Node::Variant(&hir::Variant { @@ -997,15 +992,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .. }) => { (self.tcx.sess.source_map().def_span(span), - fields.iter().map(|field| { + fields.iter().map(|field| ArgKind::Arg(field.ident.to_string(), "_".to_string()) - }).collect::>()) + ).collect::>()) } Node::StructCtor(ref variant_data) => { (self.tcx.sess.source_map().def_span(self.tcx.hir.span(variant_data.id())), - variant_data.fields() - .iter().map(|_| ArgKind::Arg("_".to_owned(), "_".to_owned())) - .collect()) + vec![ArgKind::empty(); variant_data.fields().len()]) } _ => panic!("non-FnLike node found: {:?}", node), } @@ -1054,7 +1047,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { found_str, ); - err.span_label(span, format!( "expected {} that takes {}", kind, expected_str)); + err.span_label(span, format!("expected {} that takes {}", kind, expected_str)); if let Some(found_span) = found_span { err.span_label(found_span, format!("takes {}", found_str)); @@ -1063,9 +1056,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // found arguments is empty (assume the user just wants to ignore args in this case). // For example, if `expected_args_length` is 2, suggest `|_, _|`. if found_args.is_empty() && is_closure { - let underscores = "_".repeat(expected_args.len()) - .split("") - .filter(|s| !s.is_empty()) + let underscores = iter::repeat("_") + .take(expected_args.len()) .collect::>() .join(", "); err.span_suggestion_with_applicability( @@ -1087,7 +1079,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if fields.len() == expected_args.len() { let sugg = fields.iter() .map(|(name, _)| name.to_owned()) - .collect::>().join(", "); + .collect::>() + .join(", "); err.span_suggestion_with_applicability(found_span, "change the closure to take multiple \ arguments instead of a single tuple", @@ -1146,7 +1139,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let inputs = trait_ref.substs.type_at(1); let sig = if let ty::Tuple(inputs) = inputs.sty { tcx.mk_fn_sig( - inputs.iter().map(|&x| x), + inputs.iter().cloned(), tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })), false, hir::Unsafety::Normal, @@ -1220,10 +1213,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let mut reported_violations = FxHashSet(); for violation in violations { - if !reported_violations.insert(violation.clone()) { - continue; + if reported_violations.insert(violation.clone()) { + err.note(&violation.error_msg()); } - err.note(&violation.error_msg()); } err } @@ -1289,10 +1281,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.need_type_info_err(body_id, span, self_ty).emit(); } else { let mut err = struct_span_err!(self.tcx.sess, - span, E0283, - "type annotations required: \ + span, E0283, + "type annotations required: \ cannot resolve `{}`", - predicate); + predicate); self.note_obligation_cause(&mut err, obligation); err.emit(); } @@ -1438,6 +1430,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ObligationCauseCode::ItemObligation(item_def_id) => { let item_name = tcx.item_path_str(item_def_id); let msg = format!("required by `{}`", item_name); + if let Some(sp) = tcx.hir.span_if_local(item_def_id) { let sp = tcx.sess.source_map().def_span(sp); err.span_note(sp, &msg); @@ -1529,9 +1522,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { parent_trait_ref.skip_binder().self_ty())); let parent_predicate = parent_trait_ref.to_predicate(); self.note_obligation_cause_code(err, - &parent_predicate, - &data.parent_code, - obligated_types); + &parent_predicate, + &data.parent_code, + obligated_types); } ObligationCauseCode::CompareImplMethodObligation { .. } => { err.note( @@ -1560,21 +1553,21 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } fn is_recursive_obligation(&self, - obligated_types: &mut Vec<&ty::TyS<'tcx>>, - cause_code: &ObligationCauseCode<'tcx>) -> bool { + obligated_types: &mut Vec<&ty::TyS<'tcx>>, + cause_code: &ObligationCauseCode<'tcx>) -> bool { if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code { let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref); - for obligated_type in obligated_types { - if obligated_type == &parent_trait_ref.skip_binder().self_ty() { - return true; - } + + if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) { + return true; } } - return false; + false } } /// Summarizes information +#[derive(Clone)] pub enum ArgKind { /// An argument of non-tuple type. Parameters are (name, ty) Arg(String, String), @@ -1592,11 +1585,11 @@ impl ArgKind { } /// Creates an `ArgKind` from the expected type of an - /// argument. This has no name (`_`) and no source spans.. - pub fn from_expected_ty(t: Ty<'_>) -> ArgKind { + /// argument. It has no name (`_`) and an optional source span. + pub fn from_expected_ty(t: Ty<'_>, span: Option) -> ArgKind { match t.sty { ty::Tuple(ref tys) => ArgKind::Tuple( - None, + span, tys.iter() .map(|ty| ("_".to_owned(), ty.sty.to_string())) .collect::>() diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 9998db4ad1d48..707af02acbf47 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -526,7 +526,7 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, if self.selcx.coinductive_match(cycle.clone().map(|s| s.obligation.predicate)) { debug!("process_child_obligations: coinductive match"); } else { - let cycle : Vec<_> = cycle.map(|c| c.obligation.clone()).collect(); + let cycle: Vec<_> = cycle.map(|c| c.obligation.clone()).collect(); self.selcx.infcx().report_overflow_error_cycle(&cycle); } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index e2dbe88354060..edf7772f2f78e 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -661,7 +661,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let predicates: Vec<_> = util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec()) - .collect(); + .collect(); debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates); @@ -707,7 +707,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; debug!("normalize_param_env_or_error: normalized predicates={:?}", - predicates); + predicates); let region_scope_tree = region::ScopeTree::default(); @@ -851,16 +851,16 @@ fn vtable_methods<'a, 'tcx>( // the method may have some early-bound lifetimes, add // regions for those - let substs = trait_ref.map_bound(|trait_ref| { - Substs::for_item(tcx, def_id, |param, _| { + let substs = trait_ref.map_bound(|trait_ref| + Substs::for_item(tcx, def_id, |param, _| match param.kind { GenericParamDefKind::Lifetime => tcx.types.re_erased.into(), GenericParamDefKind::Type {..} => { trait_ref.substs[param.index as usize] } } - }) - }); + ) + ); // the trait type may have higher-ranked lifetimes in it; // so erase them if they appear, so that we get the type diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 17d55b77625b2..0046a23a085e7 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -124,20 +124,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // Check methods for violations. let mut violations: Vec<_> = self.associated_items(trait_def_id) .filter(|item| item.kind == ty::AssociatedKind::Method) - .filter_map(|item| { + .filter_map(|item| self.object_safety_violation_for_method(trait_def_id, &item) .map(|code| ObjectSafetyViolation::Method(item.ident.name, code)) - }).filter(|violation| { + ).filter(|violation| { if let ObjectSafetyViolation::Method(_, - MethodViolationCode::WhereClauseReferencesSelf(span)) = violation { - // Using`CRATE_NODE_ID` is wrong, but it's hard to get a more precise id. + MethodViolationCode::WhereClauseReferencesSelf(span)) = violation + { + // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id. // It's also hard to get a use site span, so we use the method definition span. self.lint_node_note( lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY, ast::CRATE_NODE_ID, *span, &format!("the trait `{}` cannot be made into an object", - self.item_path_str(trait_def_id)), + self.item_path_str(trait_def_id)), &violation.error_msg()); false } else { @@ -213,24 +214,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let predicates = self.predicates_of(def_id); let predicates = predicates.instantiate_identity(self).predicates; elaborate_predicates(self, predicates) - .any(|predicate| { - match predicate { - ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => { - trait_pred.skip_binder().self_ty().is_self() - } - ty::Predicate::Projection(..) | - ty::Predicate::Trait(..) | - ty::Predicate::Subtype(..) | - ty::Predicate::RegionOutlives(..) | - ty::Predicate::WellFormed(..) | - ty::Predicate::ObjectSafe(..) | - ty::Predicate::ClosureKind(..) | - ty::Predicate::TypeOutlives(..) | - ty::Predicate::ConstEvaluatable(..) => { - false - } + .any(|predicate| match predicate { + ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => { + trait_pred.skip_binder().self_ty().is_self() } - }) + ty::Predicate::Projection(..) | + ty::Predicate::Trait(..) | + ty::Predicate::Subtype(..) | + ty::Predicate::RegionOutlives(..) | + ty::Predicate::WellFormed(..) | + ty::Predicate::ObjectSafe(..) | + ty::Predicate::ClosureKind(..) | + ty::Predicate::TypeOutlives(..) | + ty::Predicate::ConstEvaluatable(..) => { + false + } + } + ) } /// Returns `Some(_)` if this method makes the containing trait not object safe. diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 280ce75720bcf..f59812c0eea98 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -74,17 +74,17 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { let condition = if is_root { None } else { - let cond = item_iter.next().ok_or_else(|| { + let cond = item_iter.next().ok_or_else(|| parse_error(tcx, span, "empty `on`-clause in `#[rustc_on_unimplemented]`", "empty on-clause here", None) - })?.meta_item().ok_or_else(|| { + )?.meta_item().ok_or_else(|| parse_error(tcx, span, "invalid `on`-clause in `#[rustc_on_unimplemented]`", "invalid on-clause here", None) - })?; + )?; attr::eval_condition(cond, &tcx.sess.parse_sess, &mut |_| true); Some(cond.clone()) }; @@ -259,9 +259,9 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { // `{from_desugaring}` is allowed Position::ArgumentNamed(s) if s == "from_desugaring" => (), // So is `{A}` if A is a type parameter - Position::ArgumentNamed(s) => match generics.params.iter().find(|param| { + Position::ArgumentNamed(s) => match generics.params.iter().find(|param| param.name == s - }) { + ) { Some(_) => (), None => { span_err!(tcx.sess, span, E0230, @@ -304,7 +304,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { let empty_string = String::new(); let parser = Parser::new(&self.0, None); - parser.map(|p| { + parser.map(|p| match p { Piece::String(s) => s, Piece::NextArgument(a) => match a.position { @@ -326,11 +326,9 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { } } }, - _ => { - bug!("broken on_unimplemented {:?} - bad format arg", self.0) - } + _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0) } } - }).collect() + ).collect() } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index e50f59cbc82c1..5ea936f750e2e 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -171,7 +171,7 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> { match (current, candidate) { (ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (), (ParamEnv(..), _) => return false, - (_, ParamEnv(..)) => { unreachable!(); } + (_, ParamEnv(..)) => unreachable!(), (_, _) => convert_to_ambiguous = (), } } @@ -419,9 +419,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, normalized_ty } - _ => { - ty - } + _ => ty } } @@ -437,12 +435,9 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, instance, promoted: None }; - match tcx.const_eval(param_env.and(cid)) { - Ok(evaluated) => { - let evaluated = evaluated.subst(self.tcx(), substs); - return self.fold_const(evaluated); - } - Err(_) => {} + if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { + let evaluated = evaluated.subst(self.tcx(), substs); + return self.fold_const(evaluated); } } } else { @@ -453,9 +448,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, instance, promoted: None }; - match tcx.const_eval(param_env.and(cid)) { - Ok(evaluated) => return self.fold_const(evaluated), - Err(_) => {} + if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { + return self.fold_const(evaluated) } } } @@ -993,7 +987,7 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>( candidate_set.mark_ambiguous(); return; } - _ => { return; } + _ => return }; // If so, extract what we know from the trait and try to come up with a good answer. @@ -1023,33 +1017,30 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>( for predicate in env_predicates { debug!("assemble_candidates_from_predicates: predicate={:?}", predicate); - match predicate { - ty::Predicate::Projection(data) => { - let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id; - - let is_match = same_def_id && infcx.probe(|_| { - let data_poly_trait_ref = - data.to_poly_trait_ref(infcx.tcx); - let obligation_poly_trait_ref = - obligation_trait_ref.to_poly_trait_ref(); - infcx.at(&obligation.cause, obligation.param_env) - .sup(obligation_poly_trait_ref, data_poly_trait_ref) - .map(|InferOk { obligations: _, value: () }| { - // FIXME(#32730) -- do we need to take obligations - // into account in any way? At the moment, no. - }) - .is_ok() - }); - - debug!("assemble_candidates_from_predicates: candidate={:?} \ - is_match={} same_def_id={}", - data, is_match, same_def_id); - - if is_match { - candidate_set.push_candidate(ctor(data)); - } + if let ty::Predicate::Projection(data) = predicate { + let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id; + + let is_match = same_def_id && infcx.probe(|_| { + let data_poly_trait_ref = + data.to_poly_trait_ref(infcx.tcx); + let obligation_poly_trait_ref = + obligation_trait_ref.to_poly_trait_ref(); + infcx.at(&obligation.cause, obligation.param_env) + .sup(obligation_poly_trait_ref, data_poly_trait_ref) + .map(|InferOk { obligations: _, value: () }| { + // FIXME(#32730) -- do we need to take obligations + // into account in any way? At the moment, no. + }) + .is_ok() + }); + + debug!("assemble_candidates_from_predicates: candidate={:?} \ + is_match={} same_def_id={}", + data, is_match, same_def_id); + + if is_match { + candidate_set.push_candidate(ctor(data)); } - _ => {} } } } @@ -1072,8 +1063,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>( return Err(()); } Err(e) => { - debug!("assemble_candidates_from_impls: selection error {:?}", - e); + debug!("assemble_candidates_from_impls: selection error {:?}", e); candidate_set.mark_error(e); return Err(()); } @@ -1295,11 +1285,11 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>( let mut env_predicates = env_predicates.filter(|data| { let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx()); let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); - selcx.infcx().probe(|_| { + selcx.infcx().probe(|_| selcx.infcx().at(&obligation.cause, obligation.param_env) .sup(obligation_poly_trait_ref, data_poly_trait_ref) .is_ok() - }) + ) }); // select the first matching one; there really ought to be one or @@ -1447,7 +1437,7 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( obligation.predicate.self_ty(), fn_sig, flag) - .map_bound(|(trait_ref, ret_type)| { + .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate { projection_ty: ty::ProjectionTy::from_ref_and_name( tcx, @@ -1456,7 +1446,7 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( ), ty: ret_type } - }); + ); confirm_param_env_candidate(selcx, obligation, predicate) } diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index fd8898dffd4f2..f5fb183ec1a5d 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -57,22 +57,19 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { debug!("c_ty = {:?}", c_ty); match &gcx.dropck_outlives(c_ty) { Ok(result) if result.is_proven() => { - match self.infcx.instantiate_query_result_and_region_obligations( + if let Ok(InferOk { value, obligations }) = + self.infcx.instantiate_query_result_and_region_obligations( self.cause, self.param_env, &orig_values, - result, - ) { - Ok(InferOk { value, obligations }) => { - let ty = self.infcx.resolve_type_vars_if_possible(&ty); - let kinds = value.into_kinds_reporting_overflows(tcx, span, ty); - return InferOk { - value: kinds, - obligations, - }; - } - - Err(_) => { /* fallthrough to error-handling code below */ } + result) + { + let ty = self.infcx.resolve_type_vars_if_possible(&ty); + let kinds = value.into_kinds_reporting_overflows(tcx, span, ty); + return InferOk { + value: kinds, + obligations, + }; } } @@ -161,12 +158,7 @@ impl<'tcx> FromIterator> for DtorckConstraint<'tcx> { fn from_iter>>(iter: I) -> Self { let mut result = Self::empty(); - for DtorckConstraint { - outlives, - dtorck_types, - overflows, - } in iter - { + for DtorckConstraint { outlives, dtorck_types, overflows } in iter { result.outlives.extend(outlives); result.dtorck_types.extend(dtorck_types); result.overflows.extend(overflows); @@ -254,7 +246,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> } } - // The following *might* require a destructor: it would deeper inspection to tell. + // The following *might* require a destructor: needs deeper inspection. ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index ea8bc3b20aae9..9b9643aab97d5 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -48,6 +48,13 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { value, self.param_env, ); + if !value.has_projections() { + return Ok(Normalized { + value: value.clone(), + obligations: vec![], + }); + } + let mut normalizer = QueryNormalizer { infcx: self.infcx, cause: self.cause, @@ -56,12 +63,6 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { error: false, anon_depth: 0, }; - if !value.has_projections() { - return Ok(Normalized { - value: value.clone(), - obligations: vec![], - }); - } let value1 = value.fold_with(&mut normalizer); if normalizer.error { @@ -154,8 +155,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx let gcx = self.infcx.tcx.global_tcx(); let mut orig_values = SmallVec::new(); - let c_data = self.infcx - .canonicalize_query(&self.param_env.and(*data), &mut orig_values); + let c_data = self.infcx.canonicalize_query( + &self.param_env.and(*data), &mut orig_values); debug!("QueryNormalizer: c_data = {:#?}", c_data); debug!("QueryNormalizer: orig_values = {:#?}", orig_values); match gcx.normalize_projection_ty(c_data) { @@ -170,12 +171,9 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx self.cause, self.param_env, &orig_values, - &result, - ) { - Ok(InferOk { - value: result, - obligations, - }) => { + &result) + { + Ok(InferOk { value: result, obligations }) => { debug!("QueryNormalizer: result = {:#?}", result); debug!("QueryNormalizer: obligations = {:#?}", obligations); self.obligations.extend(obligations); @@ -212,12 +210,9 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx instance, promoted: None, }; - match tcx.const_eval(param_env.and(cid)) { - Ok(evaluated) => { - let evaluated = evaluated.subst(self.tcx(), substs); - return self.fold_const(evaluated); - } - Err(_) => {} + if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { + let evaluated = evaluated.subst(self.tcx(), substs); + return self.fold_const(evaluated); } } } else { @@ -228,9 +223,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx instance, promoted: None, }; - match tcx.const_eval(param_env.and(cid)) { - Ok(evaluated) => return self.fold_const(evaluated), - Err(_) => {} + if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { + return self.fold_const(evaluated) } } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 85e7368bfdd10..c6099e15f8bb5 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -55,7 +55,6 @@ use rustc_target::spec::abi::Abi; use hir; use util::nodemap::{FxHashMap, FxHashSet}; - pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, @@ -149,7 +148,7 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> { #[derive(Clone)] pub struct SelectionCache<'tcx> { hashmap: Lock, - WithDepNode>>>>, + WithDepNode>>>>, } /// The selection process begins by considering all impls, where @@ -623,9 +622,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation: &PredicateObligation<'tcx>) -> Result { - self.probe(|this, _| { + self.probe(|this, _| this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) - }) + ) } /// Evaluates the predicates in `predicates` recursively. Note that @@ -717,13 +716,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.infcx.projection_cache.borrow_mut().complete(key); } result - } - Ok(None) => { - Ok(EvaluatedToAmbig) - } - Err(_) => { - Ok(EvaluatedToErr) - } + }, + Ok(None) => Ok(EvaluatedToAmbig), + Err(_) => Ok(EvaluatedToErr) } } @@ -735,10 +730,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } else { Ok(EvaluatedToErr) } - } - None => { - Ok(EvaluatedToAmbig) - } + }, + None => Ok(EvaluatedToAmbig) } } @@ -901,13 +894,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // same unbound type variable. if let Some(rec_index) = stack.iter() - .skip(1) // skip top-most frame - .position(|prev| stack.obligation.param_env == prev.obligation.param_env && - stack.fresh_trait_ref == prev.fresh_trait_ref) + .skip(1) // skip top-most frame + .position(|prev| stack.obligation.param_env == prev.obligation.param_env && + stack.fresh_trait_ref == prev.fresh_trait_ref) { debug!("evaluate_stack({:?}) --> recursive", stack.fresh_trait_ref); - let cycle = stack.iter().skip(1).take(rec_index+1); + let cycle = stack.iter().skip(1).take(rec_index + 1); let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate)); if self.coinductive_match(cycle) { debug!("evaluate_stack({:?}) --> recursive, coinductive", @@ -947,10 +940,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let result = match predicate { ty::Predicate::Trait(ref data) => { self.tcx().trait_is_auto(data.def_id()) - } - _ => { - false - } + }, + _ => false }; debug!("coinductive_predicate({:?}) = {:?}", predicate, result); result @@ -1088,9 +1079,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // If no match, compute result and insert into cache. - let (candidate, dep_node) = self.in_task(|this| { + let (candidate, dep_node) = self.in_task(|this| this.candidate_from_obligation_no_cache(stack) - }); + ); debug!("CACHE MISS: SELECT({:?})={:?}", cache_fresh_trait_pred, candidate); @@ -1104,9 +1095,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn in_task(&mut self, op: OP) -> (R, DepNodeIndex) where OP: FnOnce(&mut Self) -> R { - let (result, dep_node) = self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || { + let (result, dep_node) = self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || op(self) - }); + ); self.tcx().dep_graph.read_index(dep_node); (result, dep_node) } @@ -1138,46 +1129,53 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return Ok(None); } - match self.is_knowable(stack) { - None => {} - Some(conflict) => { - debug!("coherence stage: not knowable"); - if self.intercrate_ambiguity_causes.is_some() { - debug!("evaluate_stack: intercrate_ambiguity_causes is some"); - // Heuristics: show the diagnostics when there are no candidates in crate. - if let Ok(candidate_set) = self.assemble_candidates(stack) { - let no_candidates_apply = - candidate_set - .vec - .iter() - .map(|c| self.evaluate_candidate(stack, &c)) - .collect::, OverflowError>>()? - .iter() - .all(|r| !r.may_apply()); - if !candidate_set.ambiguous && no_candidates_apply { - let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; - let self_ty = trait_ref.self_ty(); - let trait_desc = trait_ref.to_string(); - let self_desc = if self_ty.has_concrete_skeleton() { - Some(self_ty.to_string()) - } else { - None - }; - let cause = if let Conflict::Upstream = conflict { - IntercrateAmbiguityCause::UpstreamCrateUpdate { - trait_desc, - self_desc, - } - } else { - IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } - }; - debug!("evaluate_stack: pushing cause = {:?}", cause); - self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + if let Some(conflict) = self.is_knowable(stack) { + debug!("coherence stage: not knowable"); + if self.intercrate_ambiguity_causes.is_some() { + debug!("evaluate_stack: intercrate_ambiguity_causes is some"); + // Heuristics: show the diagnostics when there are no candidates in crate. + if let Ok(candidate_set) = self.assemble_candidates(stack) { + let mut no_candidates_apply = true; + { + let evaluated_candidates = candidate_set.vec.iter().map(|c| + self.evaluate_candidate(stack, &c)); + + for ec in evaluated_candidates { + match ec { + Ok(c) => { + if c.may_apply() { + no_candidates_apply = false; + break + } + }, + Err(e) => return Err(e.into()) + } } } + + if !candidate_set.ambiguous && no_candidates_apply { + let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; + let self_ty = trait_ref.self_ty(); + let trait_desc = trait_ref.to_string(); + let self_desc = if self_ty.has_concrete_skeleton() { + Some(self_ty.to_string()) + } else { + None + }; + let cause = if let Conflict::Upstream = conflict { + IntercrateAmbiguityCause::UpstreamCrateUpdate { + trait_desc, + self_desc, + } + } else { + IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } + }; + debug!("evaluate_stack: pushing cause = {:?}", cause); + self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + } } - return Ok(None); } + return Ok(None); } let candidate_set = self.assemble_candidates(stack)?; @@ -1434,9 +1432,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Other bounds. Consider both in-scope bounds from fn decl // and applicable impls. There is a certain set of precedence rules here. - let def_id = obligation.predicate.def_id(); let lang_items = self.tcx().lang_items(); + if lang_items.copy_trait() == Some(def_id) { debug!("obligation self ty is {:?}", obligation.predicate.skip_binder().self_ty()); @@ -1495,15 +1493,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::Projection(_) | ty::Opaque(..) => {} ty::Infer(ty::TyVar(_)) => { span_bug!(obligation.cause.span, - "Self=_ should have been handled by assemble_candidates"); + "Self=_ should have been handled by assemble_candidates"); } _ => return } - let result = self.probe(|this, snapshot| { + let result = self.probe(|this, snapshot| this.match_projection_obligation_against_definition_bounds(obligation, snapshot) - }); + ); if result { candidates.vec.push(ProjectionCandidate); @@ -1533,7 +1531,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { span_bug!( obligation.cause.span, "match_projection_obligation_against_definition_bounds() called \ - but self-ty not a projection: {:?}", + but self-ty is not a projection: {:?}", skol_trait_predicate.trait_ref.self_ty()); } }; @@ -1637,14 +1635,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { where_clause_trait_ref: ty::PolyTraitRef<'tcx>) -> Result { - self.probe(move |this, _| { + self.probe(move |this, _| match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { Ok(obligations) => { this.evaluate_predicates_recursively(stack.list(), obligations.iter()) } Err(()) => Ok(EvaluatedToErr) } - }) + ) } fn assemble_generator_candidates(&mut self, @@ -1667,15 +1665,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation); candidates.vec.push(GeneratorCandidate); - Ok(()) } ty::Infer(ty::TyVar(_)) => { debug!("assemble_generator_candidates: ambiguous self-type"); candidates.ambiguous = true; - return Ok(()); } - _ => { return Ok(()); } + _ => {} } + + Ok(()) } /// Check for the artificial impl that the compiler will create for an obligation like `X : @@ -1712,16 +1710,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("assemble_unboxed_candidates: closure_kind not yet known"); candidates.vec.push(ClosureCandidate); } - }; - Ok(()) + } } ty::Infer(ty::TyVar(_)) => { debug!("assemble_unboxed_closure_candidates: ambiguous self-type"); candidates.ambiguous = true; - return Ok(()); } - _ => { return Ok(()); } + _ => {} } + + Ok(()) } /// Implement one of the `Fn()` family for a fn pointer. @@ -1742,7 +1740,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("assemble_fn_pointer_candidates: ambiguous self-type"); candidates.ambiguous = true; // could wind up being a fn() type } - // provide an impl, but only for suitable `fn` pointers ty::FnDef(..) | ty::FnPtr(_) => { if let ty::FnSig { @@ -1754,8 +1751,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { candidates.vec.push(FnPointerCandidate); } } - - _ => { } + _ => {} } Ok(()) @@ -1773,18 +1769,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.predicate.def_id(), obligation.predicate.skip_binder().trait_ref.self_ty(), |impl_def_id| { - self.probe(|this, snapshot| { /* [1] */ - match this.match_impl(impl_def_id, obligation, snapshot) { - Ok(skol_map) => { - candidates.vec.push(ImplCandidate(impl_def_id)); - - // NB: we can safely drop the skol map - // since we are in a probe [1] - mem::drop(skol_map); - } - Err(_) => { } + self.probe(|this, snapshot| /* [1] */ + if let Ok(skol_map) = this.match_impl(impl_def_id, obligation, snapshot) { + candidates.vec.push(ImplCandidate(impl_def_id)); + + // NB: we can safely drop the skol map + // since we are in a probe [1] + mem::drop(skol_map); } - }); + ); } ); @@ -1874,7 +1867,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::Dynamic(ref data, ..) => { if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { debug!("assemble_candidates_from_object_ty: matched builtin bound, \ - pushing candidate"); + pushing candidate"); candidates.vec.push(BuiltinObjectCandidate); return; } @@ -1889,9 +1882,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { candidates.ambiguous = true; // could wind up being an object type return; } - _ => { - return; - } + _ => return }; debug!("assemble_candidates_from_object_ty: poly_trait_ref={:?}", @@ -1904,12 +1895,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // but `Foo` is declared as `trait Foo : Bar`. let upcast_trait_refs = util::supertraits(this.tcx(), poly_trait_ref) - .filter(|upcast_trait_ref| { + .filter(|upcast_trait_ref| this.probe(|this, _| { let upcast_trait_ref = upcast_trait_ref.clone(); this.match_poly_trait_ref(obligation, upcast_trait_ref).is_ok() }) - }) + ) .count(); if upcast_trait_refs > 1 { @@ -2028,6 +2019,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { other: &EvaluatedCandidate<'tcx>) -> bool { + if victim.candidate == other.candidate { + return true; + } + // Check if a bound would previously have been removed when normalizing // the param_env so that it can be given the lowest priority. See // #50825 for the motivation for this. @@ -2035,10 +2030,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { cand.is_global() && !cand.has_late_bound_regions() }; - if victim.candidate == other.candidate { - return true; - } - match other.candidate { // Prefer BuiltinCandidate { has_nested: false } to anything else. // This is a fix for #53123 and prevents winnowing from accidentally extending the @@ -2046,9 +2037,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { BuiltinCandidate { has_nested: false } => true, ParamCandidate(ref cand) => match victim.candidate { AutoImplCandidate(..) => { - bug!( - "default implementations shouldn't be recorded \ - when there are other valid candidates"); + bug!("default implementations shouldn't be recorded \ + when there are other valid candidates"); } // Prefer BuiltinCandidate { has_nested: false } to anything else. // This is a fix for #53123 and prevents winnowing from accidentally extending the @@ -2077,9 +2067,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ObjectCandidate | ProjectionCandidate => match victim.candidate { AutoImplCandidate(..) => { - bug!( - "default implementations shouldn't be recorded \ - when there are other valid candidates"); + bug!("default implementations shouldn't be recorded \ + when there are other valid candidates"); } // Prefer BuiltinCandidate { has_nested: false } to anything else. // This is a fix for #53123 and prevents winnowing from accidentally extending the @@ -2151,7 +2140,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn assemble_builtin_bound_candidates<'o>(&mut self, conditions: BuiltinImplConditions<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>) - -> Result<(),SelectionError<'tcx>> + -> Result<(), SelectionError<'tcx>> { match conditions { BuiltinImplConditions::Where(nested) => { @@ -2159,18 +2148,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { candidates.vec.push(BuiltinCandidate { has_nested: nested.skip_binder().len() > 0 }); - Ok(()) } - BuiltinImplConditions::None => { Ok(()) } + BuiltinImplConditions::None => {} BuiltinImplConditions::Ambiguous => { debug!("assemble_builtin_bound_candidates: ambiguous builtin"); - Ok(candidates.ambiguous = true) + candidates.ambiguous = true; } } + + Ok(()) } - fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>) - -> BuiltinImplConditions<'tcx> + fn sized_conditions(&mut self, + obligation: &TraitObligation<'tcx>) + -> BuiltinImplConditions<'tcx> { use self::BuiltinImplConditions::{Ambiguous, None, Where}; @@ -2216,8 +2207,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } - fn copy_clone_conditions(&mut self, obligation: &TraitObligation<'tcx>) - -> BuiltinImplConditions<'tcx> + fn copy_clone_conditions(&mut self, + obligation: &TraitObligation<'tcx>) + -> BuiltinImplConditions<'tcx> { // NOTE: binder moved to (*) let self_ty = self.infcx.shallow_resolve( @@ -2551,17 +2543,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let lang_items = self.tcx().lang_items(); let obligations = if has_nested { let trait_def = obligation.predicate.def_id(); - let conditions = match trait_def { - _ if Some(trait_def) == lang_items.sized_trait() => { + let conditions = + if Some(trait_def) == lang_items.sized_trait() { self.sized_conditions(obligation) - } - _ if Some(trait_def) == lang_items.copy_trait() => { + } else if Some(trait_def) == lang_items.copy_trait() { self.copy_clone_conditions(obligation) - } - _ if Some(trait_def) == lang_items.clone_trait() => { + } else if Some(trait_def) == lang_items.clone_trait() { self.copy_clone_conditions(obligation) - } - _ => bug!("unexpected builtin trait {:?}", trait_def) + } else { + bug!("unexpected builtin trait {:?}", trait_def) }; let nested = match conditions { BuiltinImplConditions::Where(nested) => nested, @@ -2608,10 +2598,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// See `confirm_auto_impl_candidate` fn vtable_auto_impl(&mut self, - obligation: &TraitObligation<'tcx>, - trait_def_id: DefId, - nested: ty::Binder>>) - -> VtableAutoImplData> + obligation: &TraitObligation<'tcx>, + trait_def_id: DefId, + nested: ty::Binder>>) + -> VtableAutoImplData> { debug!("vtable_auto_impl: nested={:?}", nested); @@ -2731,10 +2721,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::Dynamic(ref data, ..) => { data.principal().unwrap().with_self_ty(self.tcx(), self_ty) } - _ => { - span_bug!(obligation.cause.span, - "object candidate with non-object"); - } + _ => span_bug!(obligation.cause.span, + "object candidate with non-object") }; let mut upcast_trait_ref = None; @@ -2752,10 +2740,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // record it for later.) let nonmatching = util::supertraits(tcx, poly_trait_ref) - .take_while(|&t| { - match - self.commit_if_ok( - |this, _| this.match_poly_trait_ref(obligation, t)) + .take_while(|&t| + match self.commit_if_ok(|this, _| + this.match_poly_trait_ref(obligation, t)) { Ok(obligations) => { upcast_trait_ref = Some(t); @@ -2764,16 +2751,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } Err(_) => { true } } - }); + ); // Additionally, for each of the nonmatching predicates that // we pass over, we sum up the set of number of vtable // entries, so that we can compute the offset for the selected // trait. - vtable_base = - nonmatching.map(|t| tcx.count_own_vtable_entries(t)) - .sum(); - + vtable_base = nonmatching.map(|t| tcx.count_own_vtable_entries(t)).sum(); } VtableObjectData { @@ -2816,7 +2800,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn confirm_generator_candidate(&mut self, obligation: &TraitObligation<'tcx>) -> Result>, - SelectionError<'tcx>> + SelectionError<'tcx>> { // ok to skip binder because the substs on generator types never // touch bound regions, they just capture the in-scope @@ -2869,10 +2853,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { debug!("confirm_closure_candidate({:?})", obligation); - let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()) { - Some(k) => k, - None => bug!("closure candidate for non-fn trait {:?}", obligation) - }; + let kind = self.tcx() + .lang_items() + .fn_trait_kind(obligation.predicate.def_id()) + .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", + obligation)); // ok to skip binder because the substs on closure types never // touch bound regions, they just capture the in-scope @@ -2901,9 +2886,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligations.extend( self.confirm_poly_trait_refs(obligation.cause.clone(), - obligation.param_env, - obligation.predicate.to_poly_trait_ref(), - trait_ref)?); + obligation.param_env, + obligation.predicate.to_poly_trait_ref(), + trait_ref)?); obligations.push(Obligation::new( obligation.cause.clone(), @@ -3008,20 +2993,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { (_, &ty::Dynamic(ref data, r)) => { let mut object_dids = data.auto_traits().chain(data.principal().map(|p| p.def_id())); - if let Some(did) = object_dids.find(|did| { - !tcx.is_object_safe(*did) - }) { + if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) { return Err(TraitNotObjectSafe(did)) } let cause = ObligationCause::new(obligation.cause.span, obligation.cause.body_id, ObjectCastObligation(target)); - let mut push = |predicate| { - nested.push(Obligation::with_depth(cause.clone(), - obligation.recursion_depth + 1, - obligation.param_env, - predicate)); + + let predicate_to_obligation = |predicate| { + Obligation::with_depth(cause.clone(), + obligation.recursion_depth + 1, + obligation.param_env, + predicate) }; // Create obligations: @@ -3030,21 +3014,22 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // words, if the object type is Foo+Send, this would create an obligation for the // Send check.) // - Projection predicates - for predicate in data.iter() { - push(predicate.with_self_ty(tcx, source)); - } + nested.extend(data.iter().map(|d| + predicate_to_obligation(d.with_self_ty(tcx, source)) + )); // We can only make objects from sized types. let tr = ty::TraitRef { def_id: tcx.require_lang_item(lang_items::SizedTraitLangItem), substs: tcx.mk_substs_trait(source, &[]), }; - push(tr.to_predicate()); + nested.push(predicate_to_obligation(tr.to_predicate())); // If the type is `Foo+'a`, ensures that the type // being cast to `Foo+'a` outlives `'a`: let outlives = ty::OutlivesPredicate(source, r); - push(ty::Binder::dummy(outlives).to_predicate()); + nested.push(predicate_to_obligation( + ty::Binder::dummy(outlives).to_predicate())); } // [T; n] -> [T]. @@ -3105,13 +3090,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Check that the source struct with the target's // unsized parameters is equal to the target. - let params = substs_a.iter().enumerate().map(|(i, &k)| { + let params = substs_a.iter().enumerate().map(|(i, &k)| if ty_params.contains(i) { substs_b.type_at(i).into() } else { k } - }); + ); let new_struct = tcx.mk_adt(def, tcx.mk_substs(params)); let InferOk { obligations, .. } = self.infcx.at(&obligation.cause, obligation.param_env) @@ -3236,10 +3221,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let InferOk { obligations, .. } = self.infcx.at(&obligation.cause, obligation.param_env) .eq(skol_obligation_trait_ref, impl_trait_ref) - .map_err(|e| { - debug!("match_impl: failed eq_trait_refs due to `{}`", e); - () - })?; + .map_err(|e| + debug!("match_impl: failed eq_trait_refs due to `{}`", e) + )?; nested_obligations.extend(obligations); if let Err(e) = self.infcx.leak_check(false, @@ -3288,7 +3272,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn match_where_clause_trait_ref(&mut self, obligation: &TraitObligation<'tcx>, where_clause_trait_ref: ty::PolyTraitRef<'tcx>) - -> Result>,()> + -> Result>, ()> { self.match_poly_trait_ref(obligation, where_clause_trait_ref) } @@ -3298,7 +3282,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn match_poly_trait_ref(&mut self, obligation: &TraitObligation<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>) - -> Result>,()> + -> Result>, ()> { debug!("match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}", obligation, @@ -3350,20 +3334,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // in fact unparameterized (or at least does not reference any // regions bound in the obligation). Still probably some // refactoring could make this nicer. - self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), obligation.predicate - .skip_binder().self_ty(), // (1) + .skip_binder() + .self_ty(), // (1) closure_type, util::TupleArgumentsFlag::No) .map_bound(|(trait_ref, _)| trait_ref) } fn generator_trait_ref_unnormalized(&mut self, - obligation: &TraitObligation<'tcx>, - closure_def_id: DefId, - substs: ty::GeneratorSubsts<'tcx>) - -> ty::PolyTraitRef<'tcx> + obligation: &TraitObligation<'tcx>, + closure_def_id: DefId, + substs: ty::GeneratorSubsts<'tcx>) + -> ty::PolyTraitRef<'tcx> { let gen_sig = substs.poly_sig(closure_def_id, self.tcx()); @@ -3375,7 +3359,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.tcx().generator_trait_ref_and_outputs(obligation.predicate.def_id(), obligation.predicate - .skip_binder().self_ty(), // (1) + .skip_binder() + .self_ty(), // (1) gen_sig) .map_bound(|(trait_ref, ..)| trait_ref) } @@ -3453,8 +3438,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { impl<'tcx> TraitObligation<'tcx> { #[allow(unused_comparisons)] pub fn derived_cause(&self, - variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>) - -> ObligationCause<'tcx> + variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>) + -> ObligationCause<'tcx> { /*! * Creates a cause for obligations that are derived from diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 9343eff9e79b4..dbd84397b597d 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -100,10 +100,10 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, } fulfill_implication(infcx, param_env, source_trait_ref, target_impl) - .unwrap_or_else(|_| { + .unwrap_or_else(|_| bug!("When translating substitutions for specialization, the expected \ specialization failed to hold") - }) + ) } specialization_graph::Node::Trait(..) => source_trait_ref.substs, }; @@ -137,17 +137,15 @@ pub fn find_associated_item<'a, 'tcx>( let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id, substs, node_item.node); let substs = infcx.tcx.erase_regions(&substs); - tcx.lift(&substs).unwrap_or_else(|| { + tcx.lift(&substs).unwrap_or_else(|| bug!("find_method: translate_substs \ returned {:?} which contains inference types/regions", - substs); - }) + substs) + ) }); (node_item.item.def_id, substs) } - None => { - bug!("{:?} not found in {:?}", item, impl_data.impl_def_id) - } + None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id) } } @@ -312,8 +310,7 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx -> Lrc { let mut sg = specialization_graph::Graph::new(); - let mut trait_impls = Vec::new(); - tcx.for_each_impl(trait_id, |impl_did| trait_impls.push(impl_did)); + let mut trait_impls = tcx.all_impls(trait_id); // The coherence checking implementation seems to rely on impls being // iterated over (roughly) in definition order, so we are sorting by @@ -367,9 +364,9 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx "first implementation here".to_string()); err.span_label(impl_span, format!("conflicting implementation{}", - overlap.self_desc - .map_or(String::new(), - |ty| format!(" for `{}`", ty)))); + overlap.self_desc + .map_or(String::new(), + |ty| format!(" for `{}`", ty)))); } Err(cname) => { let msg = match to_pretty_impl_header(tcx, overlap.with_impl) { @@ -428,7 +425,9 @@ fn to_pretty_impl_header(tcx: TyCtxt, impl_def_id: DefId) -> Option { // The predicates will contain default bounds like `T: Sized`. We need to // remove these bounds, and add `T: ?Sized` to any untouched type parameters. let predicates = tcx.predicates_of(impl_def_id).predicates; - let mut pretty_predicates = Vec::with_capacity(predicates.len()); + let mut pretty_predicates = Vec::with_capacity( + predicates.len() + types_without_default_bounds.len()); + for p in predicates { if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() { if Some(poly_trait_ref.def_id()) == sized_trait { @@ -438,9 +437,11 @@ fn to_pretty_impl_header(tcx: TyCtxt, impl_def_id: DefId) -> Option { } pretty_predicates.push(p.to_string()); } + pretty_predicates.extend( types_without_default_bounds.iter().map(|ty| format!("{}: ?Sized", ty)) ); + if !pretty_predicates.is_empty() { write!(w, "\n where {}", pretty_predicates.join(", ")).unwrap(); } diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index a7652574c1a2e..756f55545bc45 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -390,11 +390,12 @@ impl Iterator for Ancestors { let cur = self.current_source.take(); if let Some(Node::Impl(cur_impl)) = cur { let parent = self.specialization_graph.parent(cur_impl); - if parent == self.trait_def_id { - self.current_source = Some(Node::Trait(parent)); + + self.current_source = if parent == self.trait_def_id { + Some(Node::Trait(parent)) } else { - self.current_source = Some(Node::Impl(parent)); - } + Some(Node::Impl(parent)) + }; } cur } diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 10e930d1c92d9..a4230707b70ca 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -166,10 +166,10 @@ impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> { match *self { super::Unimplemented => Some(super::Unimplemented), super::OutputTypeParameterMismatch(a, b, ref err) => { - tcx.lift(&(a, b)).and_then(|(a, b)| { + tcx.lift(&(a, b)).and_then(|(a, b)| tcx.lift(err) .map(|err| super::OutputTypeParameterMismatch(a, b, err)) - }) + ) } super::TraitNotObjectSafe(def_id) => Some(super::TraitNotObjectSafe(def_id)), super::ConstEvalFailure(ref err) => tcx.lift(&**err).map(|err| super::ConstEvalFailure( @@ -193,10 +193,10 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::ReferenceOutlivesReferent(ty) => { tcx.lift(&ty).map(super::ReferenceOutlivesReferent) } - super::ObjectTypeBound(ty, r) => tcx.lift(&ty).and_then(|ty| { + super::ObjectTypeBound(ty, r) => tcx.lift(&ty).and_then(|ty| tcx.lift(&r) - .and_then(|r| Some(super::ObjectTypeBound(ty, r))) - }), + .and_then(|r| Some(super::ObjectTypeBound(ty, r))) + ), super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation), super::AssignmentLhsSized => Some(super::AssignmentLhsSized), super::TupleInitializerSized => Some(super::TupleInitializerSized), @@ -245,13 +245,13 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> { type Lifted = traits::DerivedObligationCause<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { - tcx.lift(&self.parent_trait_ref).and_then(|trait_ref| { + tcx.lift(&self.parent_trait_ref).and_then(|trait_ref| tcx.lift(&*self.parent_code) - .map(|code| traits::DerivedObligationCause { - parent_trait_ref: trait_ref, - parent_code: Rc::new(code), - }) - }) + .map(|code| traits::DerivedObligationCause { + parent_trait_ref: trait_ref, + parent_code: Rc::new(code), + }) + ) } } @@ -275,40 +275,40 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> { impl_def_id, substs, nested, - }) => tcx.lift(&substs).map(|substs| { + }) => tcx.lift(&substs).map(|substs| traits::VtableImpl(traits::VtableImplData { impl_def_id, substs, nested, }) - }), + ), traits::VtableAutoImpl(t) => Some(traits::VtableAutoImpl(t)), traits::VtableGenerator(traits::VtableGeneratorData { generator_def_id, substs, nested, - }) => tcx.lift(&substs).map(|substs| { + }) => tcx.lift(&substs).map(|substs| traits::VtableGenerator(traits::VtableGeneratorData { generator_def_id: generator_def_id, substs: substs, nested: nested, }) - }), + ), traits::VtableClosure(traits::VtableClosureData { closure_def_id, substs, nested, - }) => tcx.lift(&substs).map(|substs| { + }) => tcx.lift(&substs).map(|substs| traits::VtableClosure(traits::VtableClosureData { closure_def_id, substs, nested, }) - }), + ), traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) => { - tcx.lift(&fn_ty).map(|fn_ty| { + tcx.lift(&fn_ty).map(|fn_ty| traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) - }) + ) } traits::VtableParam(n) => Some(traits::VtableParam(n)), traits::VtableBuiltin(n) => Some(traits::VtableBuiltin(n)), @@ -316,13 +316,13 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> { upcast_trait_ref, vtable_base, nested, - }) => tcx.lift(&upcast_trait_ref).map(|trait_ref| { + }) => tcx.lift(&upcast_trait_ref).map(|trait_ref| traits::VtableObject(traits::VtableObjectData { upcast_trait_ref: trait_ref, vtable_base, nested, }) - }), + ), } } } diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 40f13ac06f56f..2ca8214daf768 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -346,8 +346,7 @@ impl<'tcx,I:Iterator>> Iterator for FilterToTraits { Some(ty::Predicate::Trait(data)) => { return Some(data.to_poly_trait_ref()); } - Some(_) => { - } + Some(_) => {} } } } diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index 6332080a1836c..fd3f7a12376d8 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -138,6 +138,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } } + + /// Return a vector containing all impls + pub fn all_impls(self, def_id: DefId) -> Vec { + let impls = self.trait_impls_of(def_id); + + impls.blanket_impls.iter().chain( + impls.non_blanket_impls.values().flatten() + ).cloned().collect() + } } // Query provider for `trait_impls_of`. diff --git a/src/librustc_codegen_llvm/back/linker.rs b/src/librustc_codegen_llvm/back/linker.rs index 95be2d82123a7..c03180c02fe63 100644 --- a/src/librustc_codegen_llvm/back/linker.rs +++ b/src/librustc_codegen_llvm/back/linker.rs @@ -1071,6 +1071,10 @@ impl<'a> Linker for WasmLd<'a> { // Make the default table accessible self.cmd.arg("--export-table"); + // Rust code should never have warnings, and warnings are often + // indicative of bugs, let's prevent them. + self.cmd.arg("--fatal-warnings"); + let mut cmd = Command::new(""); ::std::mem::swap(&mut cmd, &mut self.cmd); cmd diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 0221cfd9b2c28..706568b544661 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -1803,13 +1803,7 @@ pub fn create_vtable_metadata( llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx), NO_SCOPE_METADATA, name.as_ptr(), - // LLVM 3.9 - // doesn't accept - // null here, so - // pass the name - // as the linkage - // name. - name.as_ptr(), + ptr::null(), unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER, vtable_type, diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 6c2601bf1ef12..a5f4137c62b14 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -8,16 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME: Rename 'DIGlobalVariable' to 'DIGlobalVariableExpression' -// once support for LLVM 3.9 is dropped. -// -// This method was changed in this LLVM patch: -// https://reviews.llvm.org/D26769 - use super::debuginfo::{ DIBuilder, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType, DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable, - DIGlobalVariable, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator, + DIGlobalVariableExpression, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator, DINameSpace, DIFlags, }; @@ -447,7 +441,7 @@ pub mod debuginfo { pub type DIDerivedType = DIType; pub type DICompositeType = DIDerivedType; pub type DIVariable = DIDescriptor; - pub type DIGlobalVariable = DIDescriptor; + pub type DIGlobalVariableExpression = DIDescriptor; pub type DIArray = DIDescriptor; pub type DISubrange = DIDescriptor; pub type DIEnumerator = DIDescriptor; @@ -1330,7 +1324,7 @@ extern "C" { Val: &'a Value, Decl: Option<&'a DIDescriptor>, AlignInBits: u32) - -> &'a DIGlobalVariable; + -> &'a DIGlobalVariableExpression; pub fn LLVMRustDIBuilderCreateVariable(Builder: &DIBuilder<'a>, Tag: c_uint, diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 02207c63b3464..adff34af61ed8 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -622,7 +622,7 @@ impl<'a> Context<'a> { } } Err(err) => { - info!("no metadata found: {}", err); + warn!("no metadata found: {}", err); continue; } }; diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index e3f7f26f53efd..0f03aa097c9df 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -316,7 +316,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { }; let ptr = base.ptr.ptr_offset(offset, self)?; - let align = base.align.min(field_layout.align); // only use static information + let align = base.align + // We do not look at `base.layout.align` nor `field_layout.align`, unlike + // codegen -- mostly to see if we can get away with that + .restrict_for_offset(offset); // must be last thing that happens Ok(MPlaceTy { mplace: MemPlace { ptr, align, extra }, layout: field_layout }) } diff --git a/src/librustc_target/spec/aarch64_pc_windows_msvc.rs b/src/librustc_target/spec/aarch64_pc_windows_msvc.rs index 8747f239d3418..c71ad5ff21da0 100644 --- a/src/librustc_target/spec/aarch64_pc_windows_msvc.rs +++ b/src/librustc_target/spec/aarch64_pc_windows_msvc.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use spec::{LinkerFlavor, Target, TargetResult, PanicStrategy, LldFlavor}; +use spec::{LinkerFlavor, Target, TargetResult, PanicStrategy}; pub fn target() -> TargetResult { let mut base = super::windows_msvc_base::opts(); @@ -17,7 +17,6 @@ pub fn target() -> TargetResult { // FIXME: this shouldn't be panic=abort, it should be panic=unwind base.panic_strategy = PanicStrategy::Abort; - base.linker = Some("rust-lld".to_owned()); Ok(Target { llvm_target: "aarch64-pc-windows-msvc".to_string(), @@ -29,7 +28,7 @@ pub fn target() -> TargetResult { target_os: "windows".to_string(), target_env: "msvc".to_string(), target_vendor: "pc".to_string(), - linker_flavor: LinkerFlavor::Lld(LldFlavor::Link), + linker_flavor: LinkerFlavor::Msvc, options: base, }) } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index a283e032e0e02..f2c20238734e6 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -504,7 +504,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .sig .inputs() .iter() - .map(|ty| ArgKind::from_expected_ty(ty)) + .map(|ty| ArgKind::from_expected_ty(ty, None)) .collect(); let (closure_span, found_args) = self.get_fn_like_arguments(expr_map_node); let expected_span = expected_sig.cause_span.unwrap_or(closure_span); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 80df7faf39d22..0dc7bc75c3d40 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3347,6 +3347,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }; } + ty::Array(_, len) => { + if let (Some(len), Ok(user_index)) = ( + len.assert_usize(self.tcx), + field.as_str().parse::() + ) { + let base = self.tcx.hir.node_to_pretty_string(base.id); + let help = "instead of using tuple indexing, use array indexing"; + let suggestion = format!("{}[{}]", base, field); + let applicability = if len < user_index { + Applicability::MachineApplicable + } else { + Applicability::MaybeIncorrect + }; + err.span_suggestion_with_applicability( + expr.span, help, suggestion, applicability + ); + } + } ty::RawPtr(..) => { let base = self.tcx.hir.node_to_pretty_string(base.id); let msg = format!("`{}` is a native pointer; try dereferencing it", base); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 3b07a2ccdde09..8a9ca924ee1ab 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -775,7 +775,7 @@ fn main() { assert_eq!(2+2, 4); }".to_string(); let output = make_test(input, None, false, &opts); - assert_eq!(output, (expected.clone(), 2)); + assert_eq!(output, (expected, 2)); } #[test] @@ -973,7 +973,7 @@ fn main() { assert_eq!(2+2, 4); }".to_string(); let output = make_test(input, None, false, &opts); - assert_eq!(output, (expected.clone(), 2)); + assert_eq!(output, (expected, 2)); } #[test] @@ -988,7 +988,7 @@ assert_eq!(2+2, 4);"; //Ceci n'est pas une `fn main` assert_eq!(2+2, 4);".to_string(); let output = make_test(input, None, true, &opts); - assert_eq!(output, (expected.clone(), 1)); + assert_eq!(output, (expected, 1)); } #[test] @@ -1003,6 +1003,6 @@ assert_eq!(2+2, 4);".to_string(); assert_eq!(2+2, 4); }".to_string(); let output = make_test(input, None, false, &opts); - assert_eq!(output, (expected.clone(), 1)); + assert_eq!(output, (expected, 1)); } } diff --git a/src/libstd/sys/wasm/cmath.rs b/src/libstd/sys/wasm/cmath.rs index 87ac2091cad41..64fc14d42d9b7 100644 --- a/src/libstd/sys/wasm/cmath.rs +++ b/src/libstd/sys/wasm/cmath.rs @@ -74,46 +74,19 @@ pub unsafe fn tanhf(n: f32) -> f32 { f64::tanh(n as f64) as f32 } -// Right now all these functions, the f64 version of the functions above, all -// shell out to random names. These names aren't actually defined anywhere, per -// se, but we need this to compile somehow. -// -// The idea with this is that when you're using wasm then, for now, we have no -// way of providing an implementation of these which delegates to a "correct" -// implementation. For example most wasm applications probably just want to -// delegate to the javascript `Math` object and its related functions, but wasm -// doesn't currently have the ability to seamlessly do that (when you -// instantiate a module you have to set that up). -// -// As a result these are just defined here with "hopefully helpful" names. The -// symbols won't ever be needed or show up unless these functions are called, -// and hopefully when they're called the errors are self-explanatory enough to -// figure out what's going on. - +// These symbols are all defined in `compiler-builtins` extern { - #[link_name = "Math_acos"] pub fn acos(n: f64) -> f64; - #[link_name = "Math_asin"] pub fn asin(n: f64) -> f64; - #[link_name = "Math_atan"] pub fn atan(n: f64) -> f64; - #[link_name = "Math_atan2"] pub fn atan2(a: f64, b: f64) -> f64; - #[link_name = "Math_cbrt"] pub fn cbrt(n: f64) -> f64; - #[link_name = "Math_cosh"] pub fn cosh(n: f64) -> f64; - #[link_name = "Math_expm1"] pub fn expm1(n: f64) -> f64; pub fn fdim(a: f64, b: f64) -> f64; - #[link_name = "Math_log1p"] pub fn log1p(n: f64) -> f64; - #[link_name = "Math_sinh"] pub fn sinh(n: f64) -> f64; - #[link_name = "Math_tan"] pub fn tan(n: f64) -> f64; - #[link_name = "Math_tanh"] pub fn tanh(n: f64) -> f64; - #[link_name = "Math_hypot"] pub fn hypot(x: f64, y: f64) -> f64; } diff --git a/src/llvm b/src/llvm index 5a081f0363340..caddcd9b9dc94 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 5a081f0363340dd895d0958955d0c84661f60f05 +Subproject commit caddcd9b9dc9479a20908d93c3e47c49b021379e diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index 29b7d508f1c1e..f8ff3d37fd23e 100644 --- a/src/rustllvm/llvm-rebuild-trigger +++ b/src/rustllvm/llvm-rebuild-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2018-09-11 +2018-09-16 diff --git a/src/test/ui/issues/issue-53712.rs b/src/test/ui/issues/issue-53712.rs new file mode 100644 index 0000000000000..2353904d79d75 --- /dev/null +++ b/src/test/ui/issues/issue-53712.rs @@ -0,0 +1,9 @@ +// issue #53712: make the error generated by using tuple indexing on an array more specific + +fn main() { + let arr = [10, 20, 30, 40, 50]; + arr.0; + //~^ ERROR no field `0` on type `[{integer}; 5]` [E0609] + //~| HELP instead of using tuple indexing, use array indexing + //~| SUGGESTION arr[0] +} diff --git a/src/test/ui/issues/issue-53712.stderr b/src/test/ui/issues/issue-53712.stderr new file mode 100644 index 0000000000000..db85919afcb55 --- /dev/null +++ b/src/test/ui/issues/issue-53712.stderr @@ -0,0 +1,11 @@ +error[E0609]: no field `0` on type `[{integer}; 5]` + --> $DIR/issue-53712.rs:5:9 + | +LL | arr.0; + | ----^ + | | + | help: instead of using tuple indexing, use array indexing: `arr[0]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/src/test/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs b/src/test/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs new file mode 100644 index 0000000000000..e35c8095fa15d --- /dev/null +++ b/src/test/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs @@ -0,0 +1,35 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// run-pass +// +// FIXME(#54366) - We probably shouldn't allow #[thread_local] static mut to get a 'static lifetime. + +#![feature(nll)] +#![feature(thread_local)] + +#[thread_local] +static mut X1: u64 = 0; + +struct S1 { + a: &'static mut u64, +} + +impl S1 { + fn new(_x: u64) -> S1 { + S1 { + a: unsafe { &mut X1 }, + } + } +} + +fn main() { + S1::new(0).a; +}