diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index e0d4095d76907..b7497c713f3df 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -2,7 +2,6 @@ use super::{AnonymousLifetimeMode, LoweringContext, ParamMode}; use super::{ImplTraitContext, ImplTraitPosition}; use crate::Arena; -use rustc_ast::node_id::NodeMap; use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::*; @@ -1351,8 +1350,11 @@ impl<'hir> LoweringContext<'_, 'hir> { generics: &Generics, itctx: ImplTraitContext<'_, 'hir>, ) -> GenericsCtor<'hir> { - // Collect `?Trait` bounds in where clause and move them to parameter definitions. - let mut add_bounds: NodeMap> = Default::default(); + // Error if `?Trait` bounds in where clauses don't refer directly to type paramters. + // Note: we used to clone these bounds directly onto the type parameter (and avoid lowering + // these into hir when we lower thee where clauses), but this makes it quite difficult to + // keep track of the Span info. Now, `add_implicitly_sized` in `AstConv` checks both param bounds and + // where clauses for `?Sized`. for pred in &generics.where_clause.predicates { if let WherePredicate::BoundPredicate(ref bound_pred) = *pred { 'next_bound: for bound in &bound_pred.bounds { @@ -1368,7 +1370,6 @@ impl<'hir> LoweringContext<'_, 'hir> { { for param in &generics.params { if def_id == self.resolver.local_def_id(param.id).to_def_id() { - add_bounds.entry(param.id).or_default().push(bound.clone()); continue 'next_bound; } } @@ -1386,7 +1387,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } GenericsCtor { - params: self.lower_generic_params_mut(&generics.params, &add_bounds, itctx).collect(), + params: self.lower_generic_params_mut(&generics.params, itctx).collect(), where_clause: self.lower_where_clause(&generics.where_clause), span: self.lower_span(generics.span), } @@ -1419,32 +1420,17 @@ impl<'hir> LoweringContext<'_, 'hir> { ref bounded_ty, ref bounds, span, - }) => { - self.with_in_scope_lifetime_defs(&bound_generic_params, |this| { - hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { - bound_generic_params: this.lower_generic_params( - bound_generic_params, - &NodeMap::default(), - ImplTraitContext::disallowed(), - ), - bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()), - bounds: this.arena.alloc_from_iter(bounds.iter().map( - |bound| match bound { - // We used to ignore `?Trait` bounds, as they were copied into type - // parameters already, but we need to keep them around only for - // diagnostics when we suggest removal of `?Sized` bounds. See - // `suggest_constraining_type_param`. This will need to change if - // we ever allow something *other* than `?Sized`. - GenericBound::Trait(p, TraitBoundModifier::Maybe) => { - hir::GenericBound::Unsized(this.lower_span(p.span)) - } - _ => this.lower_param_bound(bound, ImplTraitContext::disallowed()), - }, - )), - span: this.lower_span(span), - }) + }) => self.with_in_scope_lifetime_defs(&bound_generic_params, |this| { + hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + bound_generic_params: this + .lower_generic_params(bound_generic_params, ImplTraitContext::disallowed()), + bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()), + bounds: this.arena.alloc_from_iter(bounds.iter().map(|bound| { + this.lower_param_bound(bound, ImplTraitContext::disallowed()) + })), + span: this.lower_span(span), }) - } + }), WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime, ref bounds, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5391d4b0c9363..fa14764c42a73 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1313,7 +1313,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy { generic_params: this.lower_generic_params( &f.generic_params, - &NodeMap::default(), ImplTraitContext::disallowed(), ), unsafety: this.lower_unsafety(f.unsafety), @@ -1998,30 +1997,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_generic_params_mut<'s>( &'s mut self, params: &'s [GenericParam], - add_bounds: &'s NodeMap>, mut itctx: ImplTraitContext<'s, 'hir>, ) -> impl Iterator> + Captures<'a> + Captures<'s> { - params - .iter() - .map(move |param| self.lower_generic_param(param, add_bounds, itctx.reborrow())) + params.iter().map(move |param| self.lower_generic_param(param, itctx.reborrow())) } fn lower_generic_params( &mut self, params: &[GenericParam], - add_bounds: &NodeMap>, itctx: ImplTraitContext<'_, 'hir>, ) -> &'hir [hir::GenericParam<'hir>] { - self.arena.alloc_from_iter(self.lower_generic_params_mut(params, add_bounds, itctx)) + self.arena.alloc_from_iter(self.lower_generic_params_mut(params, itctx)) } fn lower_generic_param( &mut self, param: &GenericParam, - add_bounds: &NodeMap>, mut itctx: ImplTraitContext<'_, 'hir>, ) -> hir::GenericParam<'hir> { - let mut bounds: Vec<_> = self + let bounds: Vec<_> = self .with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| { this.lower_param_bounds_mut(¶m.bounds, itctx.reborrow()).collect() }); @@ -2057,12 +2051,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (param_name, kind) } GenericParamKind::Type { ref default, .. } => { - let add_bounds = add_bounds.get(¶m.id).map_or(&[][..], |x| &x); - if !add_bounds.is_empty() { - let params = self.lower_param_bounds_mut(add_bounds, itctx.reborrow()); - bounds.extend(params); - } - let kind = hir::GenericParamKind::Type { default: default.as_ref().map(|x| { self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Other)) @@ -2123,11 +2111,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p: &PolyTraitRef, mut itctx: ImplTraitContext<'_, 'hir>, ) -> hir::PolyTraitRef<'hir> { - let bound_generic_params = self.lower_generic_params( - &p.bound_generic_params, - &NodeMap::default(), - itctx.reborrow(), - ); + let bound_generic_params = + self.lower_generic_params(&p.bound_generic_params, itctx.reborrow()); let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| { // Any impl Trait types defined within this scope can capture diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 21fe894c6fcd3..84bc37170c634 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -441,10 +441,12 @@ pub enum GenericBound<'hir> { Trait(PolyTraitRef<'hir>, TraitBoundModifier), // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem` LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>), - Unsized(Span), Outlives(Lifetime), } +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +rustc_data_structures::static_assert_size!(GenericBound<'_>, 48); + impl GenericBound<'_> { pub fn trait_ref(&self) -> Option<&TraitRef<'_>> { match self { @@ -458,7 +460,6 @@ impl GenericBound<'_> { GenericBound::Trait(t, ..) => t.span, GenericBound::LangItemTrait(_, span, ..) => *span, GenericBound::Outlives(l) => l.span, - GenericBound::Unsized(span) => *span, } } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 2dd49eba4427a..137782a6dc78d 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -871,7 +871,6 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericB visitor.visit_generic_args(span, args); } GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime), - GenericBound::Unsized(_) => {} } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 42e51f4bb48c7..36054c0484782 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2232,9 +2232,6 @@ impl<'a> State<'a> { GenericBound::Outlives(lt) => { self.print_lifetime(lt); } - GenericBound::Unsized(_) => { - self.s.word("?Sized"); - } } } } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 4cfb104bee3a4..092eae0fc5c23 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -2,7 +2,6 @@ use crate::ty::TyKind::*; use crate::ty::{InferTy, TyCtxt, TyS}; -use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -114,10 +113,8 @@ fn suggest_removing_unsized_bound( def_id: Option, ) { // See if there's a `?Sized` bound that can be removed to suggest that. - // First look at the `where` clause because we can have `where T: ?Sized`, but that - // `?Sized` bound is *also* included in the `GenericParam` as a bound, which breaks - // the spans. Hence the somewhat involved logic that follows. - let mut where_unsized_bounds = FxHashSet::default(); + // First look at the `where` clause because we can have `where T: ?Sized`, + // then look at params. for (where_pos, predicate) in generics.where_clause.predicates.iter().enumerate() { match predicate { WherePredicate::BoundPredicate(WhereBoundPredicate { @@ -140,7 +137,6 @@ fn suggest_removing_unsized_bound( }) if segment.ident.as_str() == param_name => { for (pos, bound) in bounds.iter().enumerate() { match bound { - hir::GenericBound::Unsized(_) => {} hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe) if poly.trait_ref.trait_def_id() == def_id => {} _ => continue, @@ -173,7 +169,6 @@ fn suggest_removing_unsized_bound( // ^^^^^^^^^ (_, pos, _, _) => bounds[pos - 1].span().shrink_to_hi().to(bound.span()), }; - where_unsized_bounds.insert(bound.span()); err.span_suggestion_verbose( sp, "consider removing the `?Sized` bound to make the \ @@ -189,8 +184,7 @@ fn suggest_removing_unsized_bound( for (pos, bound) in param.bounds.iter().enumerate() { match bound { hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe) - if poly.trait_ref.trait_def_id() == def_id - && !where_unsized_bounds.contains(&bound.span()) => + if poly.trait_ref.trait_def_id() == def_id => { let sp = match (param.bounds.len(), pos) { // T: ?Sized, diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 08ed9ec73c875..3e99f4e29ef36 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -693,7 +693,6 @@ impl<'tcx> DumpVisitor<'tcx> { (Some(self.tcx.require_lang_item(lang_item, Some(span))), span) } hir::GenericBound::Outlives(..) => continue, - hir::GenericBound::Unsized(_) => continue, }; if let Some(id) = def_id { diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index a795a52a25c46..51bb09e4c54ba 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -111,11 +111,6 @@ pub trait AstConv<'tcx> { fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span); } -pub enum SizedByDefault { - Yes, - No, -} - #[derive(Debug)] struct ConvertedBinding<'a, 'tcx> { hir_id: hir::HirId, @@ -698,6 +693,61 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) } + fn instantiate_poly_trait_ref_inner( + &self, + hir_id: hir::HirId, + span: Span, + binding_span: Option, + constness: ty::BoundConstness, + bounds: &mut Bounds<'tcx>, + speculative: bool, + trait_ref_span: Span, + trait_def_id: DefId, + trait_segment: &hir::PathSegment<'_>, + args: &GenericArgs<'_>, + infer_args: bool, + self_ty: Ty<'tcx>, + ) -> GenericArgCountResult { + let (substs, arg_count) = self.create_substs_for_ast_path( + trait_ref_span, + trait_def_id, + &[], + trait_segment, + args, + infer_args, + Some(self_ty), + ); + + let tcx = self.tcx(); + let bound_vars = tcx.late_bound_vars(hir_id); + debug!(?bound_vars); + + let assoc_bindings = self.create_assoc_bindings_for_generic_args(args); + + let poly_trait_ref = + ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars); + + debug!(?poly_trait_ref, ?assoc_bindings); + bounds.trait_bounds.push((poly_trait_ref, span, constness)); + + let mut dup_bindings = FxHashMap::default(); + for binding in &assoc_bindings { + // Specify type to assert that error was already reported in `Err` case. + let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding( + hir_id, + poly_trait_ref, + binding, + bounds, + speculative, + &mut dup_bindings, + binding_span.unwrap_or(binding.span), + ); + // Okay to ignore `Err` because of `ErrorReported` (see above). + } + + arg_count + } + /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct /// a full trait reference. The resulting trait reference is returned. This may also generate /// auxiliary bounds, which are added to `bounds`. @@ -718,7 +768,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly, /// however. #[tracing::instrument(level = "debug", skip(self, span, constness, bounds, speculative))] - pub fn instantiate_poly_trait_ref( + pub(crate) fn instantiate_poly_trait_ref( &self, trait_ref: &hir::TraitRef<'_>, span: Span, @@ -727,48 +777,34 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { bounds: &mut Bounds<'tcx>, speculative: bool, ) -> GenericArgCountResult { + let hir_id = trait_ref.hir_ref_id; + let binding_span = None; + let trait_ref_span = trait_ref.path.span; let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); + let trait_segment = trait_ref.path.segments.last().unwrap(); + let args = trait_segment.args(); + let infer_args = trait_segment.infer_args; self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1); + self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment); - let tcx = self.tcx(); - let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id); - debug!(?bound_vars); - - let (substs, arg_count) = self.create_substs_for_ast_trait_ref( - trait_ref.path.span, + self.instantiate_poly_trait_ref_inner( + hir_id, + span, + binding_span, + constness, + bounds, + speculative, + trait_ref_span, trait_def_id, + trait_segment, + args, + infer_args, self_ty, - trait_ref.path.segments.last().unwrap(), - ); - let assoc_bindings = self - .create_assoc_bindings_for_generic_args(trait_ref.path.segments.last().unwrap().args()); - - let poly_trait_ref = - ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars); - - debug!(?poly_trait_ref, ?assoc_bindings); - bounds.trait_bounds.push((poly_trait_ref, span, constness)); - - let mut dup_bindings = FxHashMap::default(); - for binding in &assoc_bindings { - // Specify type to assert that error was already reported in `Err` case. - let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding( - trait_ref.hir_ref_id, - poly_trait_ref, - binding, - bounds, - speculative, - &mut dup_bindings, - binding.span, - ); - // Okay to ignore `Err` because of `ErrorReported` (see above). - } - - arg_count + ) } - pub fn instantiate_lang_item_trait_ref( + pub(crate) fn instantiate_lang_item_trait_ref( &self, lang_item: hir::LangItem, span: Span, @@ -777,36 +813,28 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, ) { + let binding_span = Some(span); + let constness = ty::BoundConstness::NotConst; + let speculative = false; + let trait_ref_span = span; let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span)); + let trait_segment = &hir::PathSegment::invalid(); + let infer_args = false; - let (substs, _) = self.create_substs_for_ast_path( + self.instantiate_poly_trait_ref_inner( + hir_id, span, + binding_span, + constness, + bounds, + speculative, + trait_ref_span, trait_def_id, - &[], - &hir::PathSegment::invalid(), + trait_segment, args, - false, - Some(self_ty), + infer_args, + self_ty, ); - let assoc_bindings = self.create_assoc_bindings_for_generic_args(args); - let tcx = self.tcx(); - let bound_vars = tcx.late_bound_vars(hir_id); - let poly_trait_ref = - ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars); - bounds.trait_bounds.push((poly_trait_ref, span, ty::BoundConstness::NotConst)); - - let mut dup_bindings = FxHashMap::default(); - for binding in assoc_bindings { - let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding( - hir_id, - poly_trait_ref, - &binding, - bounds, - false, - &mut dup_bindings, - span, - ); - } } fn ast_path_to_mono_trait_ref( @@ -853,46 +881,76 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .is_some() } - // Returns `true` if a bounds list includes `?Sized`. - pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool { + // Sets `implicitly_sized` to true on `Bounds` if necessary + pub(crate) fn add_implicitly_sized<'hir>( + &self, + bounds: &mut Bounds<'hir>, + ast_bounds: &'hir [hir::GenericBound<'hir>], + self_ty_where_predicates: Option<(hir::HirId, &'hir [hir::WherePredicate<'hir>])>, + span: Span, + ) { let tcx = self.tcx(); // Try to find an unbound in bounds. let mut unbound = None; - for ab in ast_bounds { - if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab { - if unbound.is_none() { - unbound = Some(&ptr.trait_ref); - } else { - tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span }); + let mut search_bounds = |ast_bounds: &'hir [hir::GenericBound<'hir>]| { + for ab in ast_bounds { + if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab { + if unbound.is_none() { + unbound = Some(&ptr.trait_ref); + } else { + tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span }); + } } } - } - - let kind_id = tcx.lang_items().require(LangItem::Sized); - match unbound { - Some(tpb) => { - // FIXME(#8559) currently requires the unbound to be built-in. - if let Ok(kind_id) = kind_id { - if tpb.path.res != Res::Def(DefKind::Trait, kind_id) { - tcx.sess.span_warn( - span, - "default bound relaxed for a type parameter, but \ - this does nothing because the given bound is not \ - a default; only `?Sized` is supported", - ); - return false; + }; + search_bounds(ast_bounds); + if let Some((self_ty, where_clause)) = self_ty_where_predicates { + let self_ty_def_id = tcx.hir().local_def_id(self_ty).to_def_id(); + for clause in where_clause { + match clause { + hir::WherePredicate::BoundPredicate(pred) => { + match pred.bounded_ty.kind { + hir::TyKind::Path(hir::QPath::Resolved(_, path)) => match path.res { + Res::Def(DefKind::TyParam, def_id) if def_id == self_ty_def_id => {} + _ => continue, + }, + _ => continue, + } + search_bounds(pred.bounds); } + _ => {} } } - _ if kind_id.is_ok() => { - return false; + } + + let sized_def_id = tcx.lang_items().require(LangItem::Sized); + match (&sized_def_id, unbound) { + (Ok(sized_def_id), Some(tpb)) + if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) => + { + // There was in fact a `?Sized` bound, return without doing anything + return; + } + (_, Some(_)) => { + // There was a `?Trait` bound, but it was not `?Sized`; warn. + tcx.sess.span_warn( + span, + "default bound relaxed for a type parameter, but \ + this does nothing because the given bound is not \ + a default; only `?Sized` is supported", + ); + // Otherwise, add implicitly sized if `Sized` is available. } + _ => { + // There was no `?Sized` bound; add implicitly sized if `Sized` is available. + } + } + if sized_def_id.is_err() { // No lang item for `Sized`, so we can't add it as a bound. - None => {} + return; } - - true + bounds.implicitly_sized = Some(span); } /// This helper takes a *converted* parameter type (`param_ty`) @@ -910,46 +968,43 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// **A note on binders:** there is an implied binder around /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref` /// for more details. - #[tracing::instrument(level = "debug", skip(self, bounds))] - fn add_bounds( + #[tracing::instrument(level = "debug", skip(self, ast_bounds, bounds))] + pub(crate) fn add_bounds<'hir, I: Iterator>>( &self, param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound<'_>], + ast_bounds: I, bounds: &mut Bounds<'tcx>, bound_vars: &'tcx ty::List, ) { for ast_bound in ast_bounds { - match *ast_bound { - hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => { - self.instantiate_poly_trait_ref( - &b.trait_ref, - b.span, - ty::BoundConstness::NotConst, + match ast_bound { + hir::GenericBound::Trait(poly_trait_ref, modifier) => { + let constness = match modifier { + hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst, + hir::TraitBoundModifier::None => ty::BoundConstness::NotConst, + hir::TraitBoundModifier::Maybe => continue, + }; + + let _ = self.instantiate_poly_trait_ref( + &poly_trait_ref.trait_ref, + poly_trait_ref.span, + constness, param_ty, bounds, false, ); } - hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => { - self.instantiate_poly_trait_ref( - &b.trait_ref, - b.span, - ty::BoundConstness::ConstIfConst, - param_ty, - bounds, - false, + &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { + self.instantiate_lang_item_trait_ref( + lang_item, span, hir_id, args, param_ty, bounds, ); } - hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) - | hir::GenericBound::Unsized(_) => {} - hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self - .instantiate_lang_item_trait_ref( - lang_item, span, hir_id, args, param_ty, bounds, - ), - hir::GenericBound::Outlives(ref l) => bounds.region_bounds.push(( - ty::Binder::bind_with_vars(self.ast_region_to_region(l, None), bound_vars), - l.span, - )), + hir::GenericBound::Outlives(lifetime) => { + let region = self.ast_region_to_region(lifetime, None); + bounds + .region_bounds + .push((ty::Binder::bind_with_vars(region, bound_vars), lifetime.span)); + } } } } @@ -970,24 +1025,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`. /// /// `span` should be the declaration size of the parameter. - pub fn compute_bounds( + pub(crate) fn compute_bounds( &self, param_ty: Ty<'tcx>, ast_bounds: &[hir::GenericBound<'_>], - sized_by_default: SizedByDefault, - span: Span, ) -> Bounds<'tcx> { - self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span) + self.compute_bounds_inner(param_ty, &ast_bounds) } /// Convert the bounds in `ast_bounds` that refer to traits which define an associated type /// named `assoc_name` into ty::Bounds. Ignore the rest. - pub fn compute_bounds_that_match_assoc_type( + pub(crate) fn compute_bounds_that_match_assoc_type( &self, param_ty: Ty<'tcx>, ast_bounds: &[hir::GenericBound<'_>], - sized_by_default: SizedByDefault, - span: Span, assoc_name: Ident, ) -> Bounds<'tcx> { let mut result = Vec::new(); @@ -1002,25 +1053,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - self.compute_bounds_inner(param_ty, &result, sized_by_default, span) + self.compute_bounds_inner(param_ty, &result) } fn compute_bounds_inner( &self, param_ty: Ty<'tcx>, ast_bounds: &[hir::GenericBound<'_>], - sized_by_default: SizedByDefault, - span: Span, ) -> Bounds<'tcx> { let mut bounds = Bounds::default(); - self.add_bounds(param_ty, ast_bounds, &mut bounds, ty::List::empty()); - - bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default { - if !self.is_unsized(ast_bounds, span) { Some(span) } else { None } - } else { - None - }; + self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty()); bounds } @@ -1212,7 +1255,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` // parameter to have a skipped binder. let param_ty = tcx.mk_ty(ty::Projection(projection_ty.skip_binder())); - self.add_bounds(param_ty, ast_bounds, bounds, candidate.bound_vars()); + self.add_bounds(param_ty, ast_bounds.iter(), bounds, candidate.bound_vars()); } } Ok(()) diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 64120510e5624..3688fa05e038e 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -14,7 +14,7 @@ //! At present, however, we do run collection across all items in the //! crate as a kind of pass. This should eventually be factored away. -use crate::astconv::{AstConv, SizedByDefault}; +use crate::astconv::AstConv; use crate::bounds::Bounds; use crate::check::intrinsic::intrinsic_operation_unsafety; use crate::constrained_generic_params as cgp; @@ -1156,18 +1156,10 @@ fn super_predicates_that_define_assoc_type( &icx, self_param_ty, &bounds, - SizedByDefault::No, - item.span, assoc_name, ) } else { - >::compute_bounds( - &icx, - self_param_ty, - &bounds, - SizedByDefault::No, - item.span, - ) + >::compute_bounds(&icx, self_param_ty, &bounds) }; let superbounds1 = superbounds1.predicates(tcx, self_param_ty); @@ -2176,12 +2168,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP let param_ty = ty::ParamTy::new(index, name).to_ty(tcx); index += 1; - let sized = SizedByDefault::Yes; - let bounds = >::compute_bounds( + let mut bounds = >::compute_bounds(&icx, param_ty, ¶m.bounds); + // Params are implicitly sized unless a `?Sized` bound is found + >::add_implicitly_sized( &icx, - param_ty, + &mut bounds, ¶m.bounds, - sized, + Some((param.hir_id, ast_generics.where_clause.predicates)), param.span, ); predicates.extend(bounds.predicates(tcx, param_ty)); @@ -2227,64 +2220,15 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP } } - for bound in bound_pred.bounds.iter() { - match bound { - hir::GenericBound::Trait(poly_trait_ref, modifier) => { - let constness = match modifier { - hir::TraitBoundModifier::None => ty::BoundConstness::NotConst, - hir::TraitBoundModifier::MaybeConst => { - ty::BoundConstness::ConstIfConst - } - // We ignore `where T: ?Sized`, it is already part of - // type parameter `T`. - hir::TraitBoundModifier::Maybe => continue, - }; - - let mut bounds = Bounds::default(); - let _ = >::instantiate_poly_trait_ref( - &icx, - &poly_trait_ref.trait_ref, - poly_trait_ref.span, - constness, - ty, - &mut bounds, - false, - ); - predicates.extend(bounds.predicates(tcx, ty)); - } - - &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { - let mut bounds = Bounds::default(); - >::instantiate_lang_item_trait_ref( - &icx, - lang_item, - span, - hir_id, - args, - ty, - &mut bounds, - ); - predicates.extend(bounds.predicates(tcx, ty)); - } - - hir::GenericBound::Unsized(_) => {} - - hir::GenericBound::Outlives(lifetime) => { - let region = - >::ast_region_to_region(&icx, lifetime, None); - predicates.insert(( - ty::Binder::bind_with_vars( - ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( - ty, region, - )), - bound_vars, - ) - .to_predicate(tcx), - lifetime.span, - )); - } - } - } + let mut bounds = Bounds::default(); + >::add_bounds( + &icx, + ty, + bound_pred.bounds.iter(), + &mut bounds, + bound_vars, + ); + predicates.extend(bounds.predicates(tcx, ty)); } hir::WherePredicate::RegionPredicate(region_pred) => { @@ -2498,45 +2442,14 @@ fn predicates_from_bound<'tcx>( param_ty: Ty<'tcx>, bound: &'tcx hir::GenericBound<'tcx>, ) -> Vec<(ty::Predicate<'tcx>, Span)> { - match *bound { - hir::GenericBound::Trait(ref tr, modifier) => { - let constness = match modifier { - hir::TraitBoundModifier::Maybe => return vec![], - hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst, - hir::TraitBoundModifier::None => ty::BoundConstness::NotConst, - }; - - let mut bounds = Bounds::default(); - let _ = astconv.instantiate_poly_trait_ref( - &tr.trait_ref, - tr.span, - constness, - param_ty, - &mut bounds, - false, - ); - bounds.predicates(astconv.tcx(), param_ty) - } - hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { - let mut bounds = Bounds::default(); - astconv.instantiate_lang_item_trait_ref( - lang_item, - span, - hir_id, - args, - param_ty, - &mut bounds, - ); - bounds.predicates(astconv.tcx(), param_ty) - } - hir::GenericBound::Unsized(_) => vec![], - hir::GenericBound::Outlives(ref lifetime) => { - let region = astconv.ast_region_to_region(lifetime, None); - let pred = ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)) - .to_predicate(astconv.tcx()); - vec![(pred, lifetime.span)] - } - } + let mut bounds = Bounds::default(); + astconv.add_bounds( + param_ty, + std::array::IntoIter::new([bound]), + &mut bounds, + ty::List::empty(), + ); + bounds.predicates(astconv.tcx(), param_ty) } fn compute_sig_of_foreign_fn_decl<'tcx>( diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index 1d08c4450afcf..2bc048ac8a0e9 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -1,5 +1,5 @@ use super::ItemCtxt; -use crate::astconv::{AstConv, SizedByDefault}; +use crate::astconv::AstConv; use rustc_hir as hir; use rustc_infer::traits::util; use rustc_middle::ty::subst::InternalSubsts; @@ -17,7 +17,7 @@ use rustc_span::Span; fn associated_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, assoc_item_def_id: DefId, - bounds: &'tcx [hir::GenericBound<'tcx>], + ast_bounds: &'tcx [hir::GenericBound<'tcx>], span: Span, ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { let item_ty = tcx.mk_projection( @@ -25,13 +25,10 @@ fn associated_type_bounds<'tcx>( InternalSubsts::identity_for_item(tcx, assoc_item_def_id), ); - let bounds = >::compute_bounds( - &ItemCtxt::new(tcx, assoc_item_def_id), - item_ty, - &bounds, - SizedByDefault::Yes, - span, - ); + let icx = ItemCtxt::new(tcx, assoc_item_def_id); + let mut bounds = >::compute_bounds(&icx, item_ty, &ast_bounds); + // Associated types are implicitly sized unless a `?Sized` bound is found + >::add_implicitly_sized(&icx, &mut bounds, &ast_bounds, None, span); let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id(); let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local()); @@ -59,21 +56,18 @@ fn associated_type_bounds<'tcx>( fn opaque_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, opaque_def_id: DefId, - bounds: &'tcx [hir::GenericBound<'tcx>], + ast_bounds: &'tcx [hir::GenericBound<'tcx>], span: Span, ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { ty::print::with_no_queries(|| { let item_ty = tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id)); - let bounds = >::compute_bounds( - &ItemCtxt::new(tcx, opaque_def_id), - item_ty, - &bounds, - SizedByDefault::Yes, - span, - ) - .predicates(tcx, item_ty); + let icx = ItemCtxt::new(tcx, opaque_def_id); + let mut bounds = >::compute_bounds(&icx, item_ty, &ast_bounds); + // Opaque types are implicitly sized unless a `?Sized` bound is found + >::add_implicitly_sized(&icx, &mut bounds, &ast_bounds, None, span); + let bounds = bounds.predicates(tcx, item_ty); debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 71348b3eb65ff..a95300217ab75 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -129,7 +129,6 @@ impl Clean for hir::GenericBound<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound { match *self { hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)), - hir::GenericBound::Unsized(_) => GenericBound::maybe_sized(cx), hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => { let def_id = cx.tcx.require_lang_item(lang_item, Some(span)); @@ -557,19 +556,13 @@ impl Clean for hir::Generics<'_> { WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds, .. } => { - if let [] | [GenericBound::TraitBound(_, hir::TraitBoundModifier::Maybe)] = - &bounds[..] - { + if bounds.is_empty() { for param in &mut generics.params { match param.kind { GenericParamDefKind::Lifetime { .. } => {} GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => { if ¶m.name == name { mem::swap(bounds, ty_bounds); - // We now keep track of `?Sized` obligations in the HIR. - // If we don't clear `ty_bounds` we end up with - // `fn foo(_: X) where X: ?Sized`. - ty_bounds.clear(); break; } } diff --git a/src/test/ui/error-codes/e0119/complex-impl.stderr b/src/test/ui/error-codes/e0119/complex-impl.stderr index 04babb0644718..6a1a502749a75 100644 --- a/src/test/ui/error-codes/e0119/complex-impl.stderr +++ b/src/test/ui/error-codes/e0119/complex-impl.stderr @@ -6,7 +6,7 @@ LL | impl External for (Q, R) {} | = note: conflicting implementation in crate `complex_impl_support`: - impl<'a, 'b, 'c, T, U, V, W> External for (T, M<'a, 'b, 'c, Box, V, W>) - where >::Output == V, ::Item == T, 'b: 'a, T: 'a, U: FnOnce<(T,)>, U: 'static, V: Iterator, V: Clone, W: Add, ::Output: Copy; + where >::Output == V, ::Item == T, 'b: 'a, T: 'a, U: 'static, U: FnOnce<(T,)>, V: Iterator, V: Clone, W: Add, ::Output: Copy; error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/complex-impl.rs:9:1 diff --git a/src/test/ui/generics/wrong-number-of-args.stderr b/src/test/ui/generics/wrong-number-of-args.stderr index 98e5cd6bab893..22da0dffbf29e 100644 --- a/src/test/ui/generics/wrong-number-of-args.stderr +++ b/src/test/ui/generics/wrong-number-of-args.stderr @@ -440,17 +440,6 @@ note: trait defined here, with 1 lifetime parameter: `'a` LL | trait GenericLifetimeAT<'a> { | ^^^^^^^^^^^^^^^^^ -- -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:169:44 - | -LL | type C = Box>; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type C<'a> = Box>; - | ++++ +++ - error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied --> $DIR/wrong-number-of-args.rs:169:26 | @@ -465,6 +454,17 @@ note: trait defined here, with 0 generic parameters LL | trait GenericLifetimeAT<'a> { | ^^^^^^^^^^^^^^^^^ +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:169:44 + | +LL | type C = Box>; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type C<'a> = Box>; + | ++++ +++ + error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:181:26 | @@ -525,17 +525,6 @@ help: add missing generic argument LL | type C = Box>; | +++ -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:201:48 - | -LL | type A = Box>; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type A<'a> = Box>; - | ++++ +++ - error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:201:26 | @@ -552,6 +541,17 @@ help: add missing generic argument LL | type A = Box>; | ++ +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:201:48 + | +LL | type A = Box>; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type A<'a> = Box>; + | ++++ +++ + error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:207:26 | @@ -609,17 +609,6 @@ help: consider introducing a named lifetime parameter LL | type D<'a> = Box>; | ++++ +++ -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:221:48 - | -LL | type E = Box>; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type E<'a> = Box>; - | ++++ +++ - error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:221:26 | @@ -634,6 +623,17 @@ note: trait defined here, with 1 generic parameter: `A` LL | trait GenericLifetimeTypeAT<'a, A> { | ^^^^^^^^^^^^^^^^^^^^^ - +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:221:48 + | +LL | type E = Box>; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type E<'a> = Box>; + | ++++ +++ + error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied --> $DIR/wrong-number-of-args.rs:227:26 | @@ -767,17 +767,6 @@ help: add missing lifetime argument LL | type B = Box>; | ++++ -error[E0106]: missing lifetime specifiers - --> $DIR/wrong-number-of-args.rs:279:56 - | -LL | type A = Box>; - | ^ expected 2 lifetime parameters - | -help: consider introducing a named lifetime parameter - | -LL | type A<'a> = Box>; - | ++++ +++++++ - error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:279:26 | @@ -794,6 +783,17 @@ help: add missing generic argument LL | type A = Box>; | ++ +error[E0106]: missing lifetime specifiers + --> $DIR/wrong-number-of-args.rs:279:56 + | +LL | type A = Box>; + | ^ expected 2 lifetime parameters + | +help: consider introducing a named lifetime parameter + | +LL | type A<'a> = Box>; + | ++++ +++++++ + error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied --> $DIR/wrong-number-of-args.rs:285:26 | diff --git a/src/test/ui/maybe-bounds-where.rs b/src/test/ui/maybe-bounds-where.rs index cf011653c2041..d7af0c4248056 100644 --- a/src/test/ui/maybe-bounds-where.rs +++ b/src/test/ui/maybe-bounds-where.rs @@ -11,6 +11,7 @@ trait Trait<'a> {} struct S4(T) where for<'a> T: ?Trait<'a>; //~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared +//~| WARN default bound relaxed for a type parameter struct S5(*const T) where T: ?Trait<'static> + ?Sized; //~^ ERROR type parameter has more than one relaxed default bound diff --git a/src/test/ui/maybe-bounds-where.stderr b/src/test/ui/maybe-bounds-where.stderr index 0ef8e9e9c795a..2aa6a8a38223d 100644 --- a/src/test/ui/maybe-bounds-where.stderr +++ b/src/test/ui/maybe-bounds-where.stderr @@ -23,23 +23,29 @@ LL | struct S4(T) where for<'a> T: ?Trait<'a>; | ^ error: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:20:18 + --> $DIR/maybe-bounds-where.rs:21:18 | LL | fn f() where T: ?Sized {} | ^ +warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported + --> $DIR/maybe-bounds-where.rs:12:11 + | +LL | struct S4(T) where for<'a> T: ?Trait<'a>; + | ^ + error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/maybe-bounds-where.rs:15:11 + --> $DIR/maybe-bounds-where.rs:16:11 | LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; | ^ warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported - --> $DIR/maybe-bounds-where.rs:15:11 + --> $DIR/maybe-bounds-where.rs:16:11 | LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; | ^ -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 6 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0203`.