Don't move ?Trait bounds to param bounds if they're in where clauses
This commit is contained in:
parent
2eaf9fe364
commit
f1f1d56d93
@ -2,7 +2,6 @@ use super::{AnonymousLifetimeMode, LoweringContext, ParamMode};
|
|||||||
use super::{ImplTraitContext, ImplTraitPosition};
|
use super::{ImplTraitContext, ImplTraitPosition};
|
||||||
use crate::Arena;
|
use crate::Arena;
|
||||||
|
|
||||||
use rustc_ast::node_id::NodeMap;
|
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
||||||
use rustc_ast::*;
|
use rustc_ast::*;
|
||||||
@ -1351,8 +1350,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
generics: &Generics,
|
generics: &Generics,
|
||||||
itctx: ImplTraitContext<'_, 'hir>,
|
itctx: ImplTraitContext<'_, 'hir>,
|
||||||
) -> GenericsCtor<'hir> {
|
) -> GenericsCtor<'hir> {
|
||||||
// Collect `?Trait` bounds in where clause and move them to parameter definitions.
|
// Error if `?Trait` bounds in where clauses don't refer directly to type paramters.
|
||||||
let mut add_bounds: NodeMap<Vec<_>> = Default::default();
|
// 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, `is_unsized` in `AstConv` checks both param bounds and
|
||||||
|
// where clauses for `?Sized`.
|
||||||
for pred in &generics.where_clause.predicates {
|
for pred in &generics.where_clause.predicates {
|
||||||
if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
|
if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
|
||||||
'next_bound: for bound in &bound_pred.bounds {
|
'next_bound: for bound in &bound_pred.bounds {
|
||||||
@ -1368,7 +1370,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
{
|
{
|
||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
if def_id == self.resolver.local_def_id(param.id).to_def_id() {
|
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;
|
continue 'next_bound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1386,7 +1387,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GenericsCtor {
|
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),
|
where_clause: self.lower_where_clause(&generics.where_clause),
|
||||||
span: self.lower_span(generics.span),
|
span: self.lower_span(generics.span),
|
||||||
}
|
}
|
||||||
@ -1419,32 +1420,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
ref bounded_ty,
|
ref bounded_ty,
|
||||||
ref bounds,
|
ref bounds,
|
||||||
span,
|
span,
|
||||||
}) => {
|
}) => self.with_in_scope_lifetime_defs(&bound_generic_params, |this| {
|
||||||
self.with_in_scope_lifetime_defs(&bound_generic_params, |this| {
|
|
||||||
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
|
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
|
||||||
bound_generic_params: this.lower_generic_params(
|
bound_generic_params: this
|
||||||
bound_generic_params,
|
.lower_generic_params(bound_generic_params, ImplTraitContext::disallowed()),
|
||||||
&NodeMap::default(),
|
|
||||||
ImplTraitContext::disallowed(),
|
|
||||||
),
|
|
||||||
bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
|
bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
|
||||||
bounds: this.arena.alloc_from_iter(bounds.iter().map(
|
bounds: this.arena.alloc_from_iter(bounds.iter().map(|bound| {
|
||||||
|bound| match bound {
|
this.lower_param_bound(bound, ImplTraitContext::disallowed())
|
||||||
// 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),
|
span: this.lower_span(span),
|
||||||
})
|
})
|
||||||
})
|
}),
|
||||||
}
|
|
||||||
WherePredicate::RegionPredicate(WhereRegionPredicate {
|
WherePredicate::RegionPredicate(WhereRegionPredicate {
|
||||||
ref lifetime,
|
ref lifetime,
|
||||||
ref bounds,
|
ref bounds,
|
||||||
|
@ -1313,7 +1313,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
|
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
|
||||||
generic_params: this.lower_generic_params(
|
generic_params: this.lower_generic_params(
|
||||||
&f.generic_params,
|
&f.generic_params,
|
||||||
&NodeMap::default(),
|
|
||||||
ImplTraitContext::disallowed(),
|
ImplTraitContext::disallowed(),
|
||||||
),
|
),
|
||||||
unsafety: this.lower_unsafety(f.unsafety),
|
unsafety: this.lower_unsafety(f.unsafety),
|
||||||
@ -1998,30 +1997,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
fn lower_generic_params_mut<'s>(
|
fn lower_generic_params_mut<'s>(
|
||||||
&'s mut self,
|
&'s mut self,
|
||||||
params: &'s [GenericParam],
|
params: &'s [GenericParam],
|
||||||
add_bounds: &'s NodeMap<Vec<GenericBound>>,
|
|
||||||
mut itctx: ImplTraitContext<'s, 'hir>,
|
mut itctx: ImplTraitContext<'s, 'hir>,
|
||||||
) -> impl Iterator<Item = hir::GenericParam<'hir>> + Captures<'a> + Captures<'s> {
|
) -> impl Iterator<Item = hir::GenericParam<'hir>> + Captures<'a> + Captures<'s> {
|
||||||
params
|
params.iter().map(move |param| self.lower_generic_param(param, itctx.reborrow()))
|
||||||
.iter()
|
|
||||||
.map(move |param| self.lower_generic_param(param, add_bounds, itctx.reborrow()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_generic_params(
|
fn lower_generic_params(
|
||||||
&mut self,
|
&mut self,
|
||||||
params: &[GenericParam],
|
params: &[GenericParam],
|
||||||
add_bounds: &NodeMap<Vec<GenericBound>>,
|
|
||||||
itctx: ImplTraitContext<'_, 'hir>,
|
itctx: ImplTraitContext<'_, 'hir>,
|
||||||
) -> &'hir [hir::GenericParam<'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(
|
fn lower_generic_param(
|
||||||
&mut self,
|
&mut self,
|
||||||
param: &GenericParam,
|
param: &GenericParam,
|
||||||
add_bounds: &NodeMap<Vec<GenericBound>>,
|
|
||||||
mut itctx: ImplTraitContext<'_, 'hir>,
|
mut itctx: ImplTraitContext<'_, 'hir>,
|
||||||
) -> hir::GenericParam<'hir> {
|
) -> hir::GenericParam<'hir> {
|
||||||
let mut bounds: Vec<_> = self
|
let bounds: Vec<_> = self
|
||||||
.with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
|
.with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
|
||||||
this.lower_param_bounds_mut(¶m.bounds, itctx.reborrow()).collect()
|
this.lower_param_bounds_mut(¶m.bounds, itctx.reborrow()).collect()
|
||||||
});
|
});
|
||||||
@ -2057,12 +2051,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
(param_name, kind)
|
(param_name, kind)
|
||||||
}
|
}
|
||||||
GenericParamKind::Type { ref default, .. } => {
|
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 {
|
let kind = hir::GenericParamKind::Type {
|
||||||
default: default.as_ref().map(|x| {
|
default: default.as_ref().map(|x| {
|
||||||
self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Other))
|
self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Other))
|
||||||
@ -2123,11 +2111,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
p: &PolyTraitRef,
|
p: &PolyTraitRef,
|
||||||
mut itctx: ImplTraitContext<'_, 'hir>,
|
mut itctx: ImplTraitContext<'_, 'hir>,
|
||||||
) -> hir::PolyTraitRef<'hir> {
|
) -> hir::PolyTraitRef<'hir> {
|
||||||
let bound_generic_params = self.lower_generic_params(
|
let bound_generic_params =
|
||||||
&p.bound_generic_params,
|
self.lower_generic_params(&p.bound_generic_params, itctx.reborrow());
|
||||||
&NodeMap::default(),
|
|
||||||
itctx.reborrow(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| {
|
let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| {
|
||||||
// Any impl Trait types defined within this scope can capture
|
// Any impl Trait types defined within this scope can capture
|
||||||
|
@ -441,7 +441,6 @@ pub enum GenericBound<'hir> {
|
|||||||
Trait(PolyTraitRef<'hir>, TraitBoundModifier),
|
Trait(PolyTraitRef<'hir>, TraitBoundModifier),
|
||||||
// FIXME(davidtwco): Introduce `PolyTraitRef::LangItem`
|
// FIXME(davidtwco): Introduce `PolyTraitRef::LangItem`
|
||||||
LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>),
|
LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>),
|
||||||
Unsized(Span),
|
|
||||||
Outlives(Lifetime),
|
Outlives(Lifetime),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,7 +460,6 @@ impl GenericBound<'_> {
|
|||||||
GenericBound::Trait(t, ..) => t.span,
|
GenericBound::Trait(t, ..) => t.span,
|
||||||
GenericBound::LangItemTrait(_, span, ..) => *span,
|
GenericBound::LangItemTrait(_, span, ..) => *span,
|
||||||
GenericBound::Outlives(l) => l.span,
|
GenericBound::Outlives(l) => l.span,
|
||||||
GenericBound::Unsized(span) => *span,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
visitor.visit_generic_args(span, args);
|
||||||
}
|
}
|
||||||
GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
|
GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
|
||||||
GenericBound::Unsized(_) => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2232,9 +2232,6 @@ impl<'a> State<'a> {
|
|||||||
GenericBound::Outlives(lt) => {
|
GenericBound::Outlives(lt) => {
|
||||||
self.print_lifetime(lt);
|
self.print_lifetime(lt);
|
||||||
}
|
}
|
||||||
GenericBound::Unsized(_) => {
|
|
||||||
self.s.word("?Sized");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
use crate::ty::TyKind::*;
|
use crate::ty::TyKind::*;
|
||||||
use crate::ty::{InferTy, TyCtxt, TyS};
|
use crate::ty::{InferTy, TyCtxt, TyS};
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
|
||||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
@ -114,10 +113,8 @@ fn suggest_removing_unsized_bound(
|
|||||||
def_id: Option<DefId>,
|
def_id: Option<DefId>,
|
||||||
) {
|
) {
|
||||||
// See if there's a `?Sized` bound that can be removed to suggest that.
|
// 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
|
// First look at the `where` clause because we can have `where T: ?Sized`,
|
||||||
// `?Sized` bound is *also* included in the `GenericParam` as a bound, which breaks
|
// then look at params.
|
||||||
// the spans. Hence the somewhat involved logic that follows.
|
|
||||||
let mut where_unsized_bounds = FxHashSet::default();
|
|
||||||
for (where_pos, predicate) in generics.where_clause.predicates.iter().enumerate() {
|
for (where_pos, predicate) in generics.where_clause.predicates.iter().enumerate() {
|
||||||
match predicate {
|
match predicate {
|
||||||
WherePredicate::BoundPredicate(WhereBoundPredicate {
|
WherePredicate::BoundPredicate(WhereBoundPredicate {
|
||||||
@ -140,7 +137,6 @@ fn suggest_removing_unsized_bound(
|
|||||||
}) if segment.ident.as_str() == param_name => {
|
}) if segment.ident.as_str() == param_name => {
|
||||||
for (pos, bound) in bounds.iter().enumerate() {
|
for (pos, bound) in bounds.iter().enumerate() {
|
||||||
match bound {
|
match bound {
|
||||||
hir::GenericBound::Unsized(_) => {}
|
|
||||||
hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe)
|
hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe)
|
||||||
if poly.trait_ref.trait_def_id() == def_id => {}
|
if poly.trait_ref.trait_def_id() == def_id => {}
|
||||||
_ => continue,
|
_ => continue,
|
||||||
@ -173,7 +169,6 @@ fn suggest_removing_unsized_bound(
|
|||||||
// ^^^^^^^^^
|
// ^^^^^^^^^
|
||||||
(_, pos, _, _) => bounds[pos - 1].span().shrink_to_hi().to(bound.span()),
|
(_, pos, _, _) => bounds[pos - 1].span().shrink_to_hi().to(bound.span()),
|
||||||
};
|
};
|
||||||
where_unsized_bounds.insert(bound.span());
|
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
sp,
|
sp,
|
||||||
"consider removing the `?Sized` bound to make the \
|
"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() {
|
for (pos, bound) in param.bounds.iter().enumerate() {
|
||||||
match bound {
|
match bound {
|
||||||
hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe)
|
hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe)
|
||||||
if poly.trait_ref.trait_def_id() == def_id
|
if poly.trait_ref.trait_def_id() == def_id =>
|
||||||
&& !where_unsized_bounds.contains(&bound.span()) =>
|
|
||||||
{
|
{
|
||||||
let sp = match (param.bounds.len(), pos) {
|
let sp = match (param.bounds.len(), pos) {
|
||||||
// T: ?Sized,
|
// T: ?Sized,
|
||||||
|
@ -693,7 +693,6 @@ impl<'tcx> DumpVisitor<'tcx> {
|
|||||||
(Some(self.tcx.require_lang_item(lang_item, Some(span))), span)
|
(Some(self.tcx.require_lang_item(lang_item, Some(span))), span)
|
||||||
}
|
}
|
||||||
hir::GenericBound::Outlives(..) => continue,
|
hir::GenericBound::Outlives(..) => continue,
|
||||||
hir::GenericBound::Unsized(_) => continue,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(id) = def_id {
|
if let Some(id) = def_id {
|
||||||
|
@ -854,7 +854,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns `true` if a bounds list includes `?Sized`.
|
// Returns `true` if a bounds list includes `?Sized`.
|
||||||
pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool {
|
fn is_unsized(
|
||||||
|
&self,
|
||||||
|
ast_bounds: &[hir::GenericBound<'_>],
|
||||||
|
self_ty: Option<hir::HirId>,
|
||||||
|
where_clause: Option<&[hir::WherePredicate<'_>]>,
|
||||||
|
span: Span,
|
||||||
|
) -> bool {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
|
||||||
// Try to find an unbound in bounds.
|
// Try to find an unbound in bounds.
|
||||||
@ -868,11 +874,38 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let (Some(self_ty), Some(where_clause)) = (self_ty, where_clause) {
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
for ab in pred.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);
|
let kind_id = tcx.lang_items().require(LangItem::Sized);
|
||||||
match unbound {
|
match unbound {
|
||||||
Some(tpb) => {
|
Some(tpb) => {
|
||||||
// FIXME(#8559) currently requires the unbound to be built-in.
|
|
||||||
if let Ok(kind_id) = kind_id {
|
if let Ok(kind_id) = kind_id {
|
||||||
if tpb.path.res != Res::Def(DefKind::Trait, kind_id) {
|
if tpb.path.res != Res::Def(DefKind::Trait, kind_id) {
|
||||||
tcx.sess.span_warn(
|
tcx.sess.span_warn(
|
||||||
@ -940,8 +973,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe)
|
hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
|
||||||
| hir::GenericBound::Unsized(_) => {}
|
|
||||||
hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
|
hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
|
||||||
.instantiate_lang_item_trait_ref(
|
.instantiate_lang_item_trait_ref(
|
||||||
lang_item, span, hir_id, args, param_ty, bounds,
|
lang_item, span, hir_id, args, param_ty, bounds,
|
||||||
@ -970,22 +1002,33 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
/// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`.
|
/// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`.
|
||||||
///
|
///
|
||||||
/// `span` should be the declaration size of the parameter.
|
/// `span` should be the declaration size of the parameter.
|
||||||
pub fn compute_bounds(
|
pub(crate) fn compute_bounds(
|
||||||
&self,
|
&self,
|
||||||
param_ty: Ty<'tcx>,
|
param_ty: Ty<'tcx>,
|
||||||
ast_bounds: &[hir::GenericBound<'_>],
|
ast_bounds: &[hir::GenericBound<'_>],
|
||||||
|
self_ty: Option<hir::HirId>,
|
||||||
|
where_clause: Option<&[hir::WherePredicate<'_>]>,
|
||||||
sized_by_default: SizedByDefault,
|
sized_by_default: SizedByDefault,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Bounds<'tcx> {
|
) -> Bounds<'tcx> {
|
||||||
self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span)
|
self.compute_bounds_inner(
|
||||||
|
param_ty,
|
||||||
|
&ast_bounds,
|
||||||
|
self_ty,
|
||||||
|
where_clause,
|
||||||
|
sized_by_default,
|
||||||
|
span,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
|
/// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
|
||||||
/// named `assoc_name` into ty::Bounds. Ignore the rest.
|
/// 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,
|
&self,
|
||||||
param_ty: Ty<'tcx>,
|
param_ty: Ty<'tcx>,
|
||||||
ast_bounds: &[hir::GenericBound<'_>],
|
ast_bounds: &[hir::GenericBound<'_>],
|
||||||
|
self_ty: Option<hir::HirId>,
|
||||||
|
where_clause: Option<&[hir::WherePredicate<'_>]>,
|
||||||
sized_by_default: SizedByDefault,
|
sized_by_default: SizedByDefault,
|
||||||
span: Span,
|
span: Span,
|
||||||
assoc_name: Ident,
|
assoc_name: Ident,
|
||||||
@ -1002,13 +1045,15 @@ 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, self_ty, where_clause, sized_by_default, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_bounds_inner(
|
fn compute_bounds_inner(
|
||||||
&self,
|
&self,
|
||||||
param_ty: Ty<'tcx>,
|
param_ty: Ty<'tcx>,
|
||||||
ast_bounds: &[hir::GenericBound<'_>],
|
ast_bounds: &[hir::GenericBound<'_>],
|
||||||
|
self_ty: Option<hir::HirId>,
|
||||||
|
where_clause: Option<&[hir::WherePredicate<'_>]>,
|
||||||
sized_by_default: SizedByDefault,
|
sized_by_default: SizedByDefault,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Bounds<'tcx> {
|
) -> Bounds<'tcx> {
|
||||||
@ -1017,7 +1062,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
self.add_bounds(param_ty, ast_bounds, &mut bounds, ty::List::empty());
|
self.add_bounds(param_ty, ast_bounds, &mut bounds, ty::List::empty());
|
||||||
|
|
||||||
bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
|
bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
|
||||||
if !self.is_unsized(ast_bounds, span) { Some(span) } else { None }
|
if !self.is_unsized(ast_bounds, self_ty, where_clause, span) {
|
||||||
|
Some(span)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -1156,6 +1156,8 @@ fn super_predicates_that_define_assoc_type(
|
|||||||
&icx,
|
&icx,
|
||||||
self_param_ty,
|
self_param_ty,
|
||||||
&bounds,
|
&bounds,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
SizedByDefault::No,
|
SizedByDefault::No,
|
||||||
item.span,
|
item.span,
|
||||||
assoc_name,
|
assoc_name,
|
||||||
@ -1165,6 +1167,8 @@ fn super_predicates_that_define_assoc_type(
|
|||||||
&icx,
|
&icx,
|
||||||
self_param_ty,
|
self_param_ty,
|
||||||
&bounds,
|
&bounds,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
SizedByDefault::No,
|
SizedByDefault::No,
|
||||||
item.span,
|
item.span,
|
||||||
)
|
)
|
||||||
@ -2181,6 +2185,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
|
|||||||
&icx,
|
&icx,
|
||||||
param_ty,
|
param_ty,
|
||||||
¶m.bounds,
|
¶m.bounds,
|
||||||
|
Some(param.hir_id),
|
||||||
|
Some(ast_generics.where_clause.predicates),
|
||||||
sized,
|
sized,
|
||||||
param.span,
|
param.span,
|
||||||
);
|
);
|
||||||
@ -2267,8 +2273,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
|
|||||||
predicates.extend(bounds.predicates(tcx, ty));
|
predicates.extend(bounds.predicates(tcx, ty));
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::GenericBound::Unsized(_) => {}
|
|
||||||
|
|
||||||
hir::GenericBound::Outlives(lifetime) => {
|
hir::GenericBound::Outlives(lifetime) => {
|
||||||
let region =
|
let region =
|
||||||
<dyn AstConv<'_>>::ast_region_to_region(&icx, lifetime, None);
|
<dyn AstConv<'_>>::ast_region_to_region(&icx, lifetime, None);
|
||||||
@ -2529,7 +2533,6 @@ fn predicates_from_bound<'tcx>(
|
|||||||
);
|
);
|
||||||
bounds.predicates(astconv.tcx(), param_ty)
|
bounds.predicates(astconv.tcx(), param_ty)
|
||||||
}
|
}
|
||||||
hir::GenericBound::Unsized(_) => vec![],
|
|
||||||
hir::GenericBound::Outlives(ref lifetime) => {
|
hir::GenericBound::Outlives(ref lifetime) => {
|
||||||
let region = astconv.ast_region_to_region(lifetime, None);
|
let region = astconv.ast_region_to_region(lifetime, None);
|
||||||
let pred = ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region))
|
let pred = ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region))
|
||||||
|
@ -29,6 +29,8 @@ fn associated_type_bounds<'tcx>(
|
|||||||
&ItemCtxt::new(tcx, assoc_item_def_id),
|
&ItemCtxt::new(tcx, assoc_item_def_id),
|
||||||
item_ty,
|
item_ty,
|
||||||
&bounds,
|
&bounds,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
SizedByDefault::Yes,
|
SizedByDefault::Yes,
|
||||||
span,
|
span,
|
||||||
);
|
);
|
||||||
@ -70,6 +72,8 @@ fn opaque_type_bounds<'tcx>(
|
|||||||
&ItemCtxt::new(tcx, opaque_def_id),
|
&ItemCtxt::new(tcx, opaque_def_id),
|
||||||
item_ty,
|
item_ty,
|
||||||
&bounds,
|
&bounds,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
SizedByDefault::Yes,
|
SizedByDefault::Yes,
|
||||||
span,
|
span,
|
||||||
)
|
)
|
||||||
|
@ -11,6 +11,7 @@ trait Trait<'a> {}
|
|||||||
|
|
||||||
struct S4<T>(T) where for<'a> T: ?Trait<'a>;
|
struct S4<T>(T) where for<'a> T: ?Trait<'a>;
|
||||||
//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
|
//~^ 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<T>(*const T) where T: ?Trait<'static> + ?Sized;
|
struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
|
||||||
//~^ ERROR type parameter has more than one relaxed default bound
|
//~^ ERROR type parameter has more than one relaxed default bound
|
||||||
|
@ -23,23 +23,29 @@ LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
|
|||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: `?Trait` bounds are only permitted at the point where a type parameter is declared
|
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 {}
|
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>(T) where for<'a> T: ?Trait<'a>;
|
||||||
|
| ^
|
||||||
|
|
||||||
error[E0203]: type parameter has more than one relaxed default bound, only one is supported
|
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<T>(*const T) where T: ?Trait<'static> + ?Sized;
|
LL | struct S5<T>(*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
|
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<T>(*const T) where T: ?Trait<'static> + ?Sized;
|
LL | struct S5<T>(*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`.
|
For more information about this error, try `rustc --explain E0203`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user