From a8ec8e5cb703a5904e8ea96dc4a7b2d96aa25f57 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 12 Sep 2018 16:57:19 +0200 Subject: [PATCH] A few cleanups and minor improvements to rustc/traits --- src/librustc/traits/auto_trait.rs | 18 +- src/librustc/traits/codegen/mod.rs | 31 +- src/librustc/traits/coherence.rs | 21 +- src/librustc/traits/error_reporting.rs | 145 ++++---- src/librustc/traits/fulfill.rs | 2 +- src/librustc/traits/mod.rs | 12 +- src/librustc/traits/object_safety.rs | 44 +-- src/librustc/traits/on_unimplemented.rs | 18 +- src/librustc/traits/project.rs | 82 ++--- src/librustc/traits/query/dropck_outlives.rs | 32 +- src/librustc/traits/query/normalize.rs | 40 +- src/librustc/traits/select.rs | 341 +++++++++--------- src/librustc/traits/specialize/mod.rs | 29 +- .../traits/specialize/specialization_graph.rs | 9 +- src/librustc/traits/structural_impls.rs | 42 +-- src/librustc/traits/util.rs | 3 +- src/librustc/ty/trait_def.rs | 9 + src/librustc_typeck/check/closure.rs | 2 +- 18 files changed, 414 insertions(+), 466 deletions(-) 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..82d4bfa521f4d 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) => { @@ -981,11 +974,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 +988,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 +1043,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 +1052,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 +1075,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 +1135,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 +1209,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 +1277,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 +1426,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 +1518,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 +1549,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 +1581,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 232ef108537fe..781cfe615a9aa 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_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);