Rollup merge of #127103 - compiler-errors:tighten-trait-bound-parsing, r=fmease
Move binder and polarity parsing into `parse_generic_ty_bound` Let's pull out the parts of #127054 which just: 1. Make the parsing code less confusing 2. Fix `?use<>` (to correctly be denied) 3. Improve `T: for<'a> 'a` diagnostics This should have no user-facing effects on stable parsing. r? fmease
This commit is contained in:
commit
a4e92bfef0
7 changed files with 204 additions and 40 deletions
|
@ -2327,7 +2327,7 @@ impl<'a> Parser<'a> {
|
||||||
let before = self.prev_token.clone();
|
let before = self.prev_token.clone();
|
||||||
let binder = if self.check_keyword(kw::For) {
|
let binder = if self.check_keyword(kw::For) {
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
|
let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?;
|
||||||
let span = lo.to(self.prev_token.span);
|
let span = lo.to(self.prev_token.span);
|
||||||
|
|
||||||
self.psess.gated_spans.gate(sym::closure_lifetime_binder, span);
|
self.psess.gated_spans.gate(sym::closure_lifetime_binder, span);
|
||||||
|
|
|
@ -457,7 +457,7 @@ impl<'a> Parser<'a> {
|
||||||
// * `for<'a> Trait1<'a>: Trait2<'a /* ok */>`
|
// * `for<'a> Trait1<'a>: Trait2<'a /* ok */>`
|
||||||
// * `(for<'a> Trait1<'a>): Trait2<'a /* not ok */>`
|
// * `(for<'a> Trait1<'a>): Trait2<'a /* not ok */>`
|
||||||
// * `for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /* ok */, 'b /* not ok */>`
|
// * `for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /* ok */, 'b /* not ok */>`
|
||||||
let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
|
let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?;
|
||||||
|
|
||||||
// Parse type with mandatory colon and (possibly empty) bounds,
|
// Parse type with mandatory colon and (possibly empty) bounds,
|
||||||
// or with mandatory equality sign and the second type.
|
// or with mandatory equality sign and the second type.
|
||||||
|
|
|
@ -18,7 +18,7 @@ use rustc_ast::{
|
||||||
};
|
};
|
||||||
use rustc_errors::{Applicability, PResult};
|
use rustc_errors::{Applicability, PResult};
|
||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{ErrorGuaranteed, Span, Symbol};
|
||||||
use thin_vec::{thin_vec, ThinVec};
|
use thin_vec::{thin_vec, ThinVec};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
|
@ -280,7 +280,7 @@ impl<'a> Parser<'a> {
|
||||||
// Function pointer type or bound list (trait object type) starting with a poly-trait.
|
// Function pointer type or bound list (trait object type) starting with a poly-trait.
|
||||||
// `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
|
// `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
|
||||||
// `for<'lt> Trait1<'lt> + Trait2 + 'a`
|
// `for<'lt> Trait1<'lt> + Trait2 + 'a`
|
||||||
let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
|
let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?;
|
||||||
if self.check_fn_front_matter(false, Case::Sensitive) {
|
if self.check_fn_front_matter(false, Case::Sensitive) {
|
||||||
self.parse_ty_bare_fn(
|
self.parse_ty_bare_fn(
|
||||||
lo,
|
lo,
|
||||||
|
@ -833,12 +833,9 @@ impl<'a> Parser<'a> {
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
let leading_token = self.prev_token.clone();
|
let leading_token = self.prev_token.clone();
|
||||||
let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis));
|
let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis));
|
||||||
let inner_lo = self.token.span;
|
|
||||||
|
|
||||||
let modifiers = self.parse_trait_bound_modifiers()?;
|
|
||||||
let bound = if self.token.is_lifetime() {
|
let bound = if self.token.is_lifetime() {
|
||||||
self.error_lt_bound_with_modifiers(modifiers);
|
self.parse_generic_lt_bound(lo, has_parens)?
|
||||||
self.parse_generic_lt_bound(lo, inner_lo, has_parens)?
|
|
||||||
} else if self.eat_keyword(kw::Use) {
|
} else if self.eat_keyword(kw::Use) {
|
||||||
// parse precise captures, if any. This is `use<'lt, 'lt, P, P>`; a list of
|
// parse precise captures, if any. This is `use<'lt, 'lt, P, P>`; a list of
|
||||||
// lifetimes and ident params (including SelfUpper). These are validated later
|
// lifetimes and ident params (including SelfUpper). These are validated later
|
||||||
|
@ -848,7 +845,7 @@ impl<'a> Parser<'a> {
|
||||||
let (args, args_span) = self.parse_precise_capturing_args()?;
|
let (args, args_span) = self.parse_precise_capturing_args()?;
|
||||||
GenericBound::Use(args, use_span.to(args_span))
|
GenericBound::Use(args, use_span.to(args_span))
|
||||||
} else {
|
} else {
|
||||||
self.parse_generic_ty_bound(lo, has_parens, modifiers, &leading_token)?
|
self.parse_generic_ty_bound(lo, has_parens, &leading_token)?
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(bound)
|
Ok(bound)
|
||||||
|
@ -858,50 +855,64 @@ impl<'a> Parser<'a> {
|
||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
/// LT_BOUND = LIFETIME
|
/// LT_BOUND = LIFETIME
|
||||||
/// ```
|
/// ```
|
||||||
fn parse_generic_lt_bound(
|
fn parse_generic_lt_bound(&mut self, lo: Span, has_parens: bool) -> PResult<'a, GenericBound> {
|
||||||
&mut self,
|
let lt = self.expect_lifetime();
|
||||||
lo: Span,
|
let bound = GenericBound::Outlives(lt);
|
||||||
inner_lo: Span,
|
|
||||||
has_parens: bool,
|
|
||||||
) -> PResult<'a, GenericBound> {
|
|
||||||
let bound = GenericBound::Outlives(self.expect_lifetime());
|
|
||||||
if has_parens {
|
if has_parens {
|
||||||
// FIXME(Centril): Consider not erroring here and accepting `('lt)` instead,
|
// FIXME(Centril): Consider not erroring here and accepting `('lt)` instead,
|
||||||
// possibly introducing `GenericBound::Paren(P<GenericBound>)`?
|
// possibly introducing `GenericBound::Paren(P<GenericBound>)`?
|
||||||
self.recover_paren_lifetime(lo, inner_lo)?;
|
self.recover_paren_lifetime(lo, lt.ident.span)?;
|
||||||
}
|
}
|
||||||
Ok(bound)
|
Ok(bound)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emits an error if any trait bound modifiers were present.
|
/// Emits an error if any trait bound modifiers were present.
|
||||||
fn error_lt_bound_with_modifiers(&self, modifiers: TraitBoundModifiers) {
|
fn error_lt_bound_with_modifiers(
|
||||||
match modifiers.constness {
|
&self,
|
||||||
|
modifiers: TraitBoundModifiers,
|
||||||
|
binder_span: Option<Span>,
|
||||||
|
) -> ErrorGuaranteed {
|
||||||
|
let TraitBoundModifiers { constness, asyncness, polarity } = modifiers;
|
||||||
|
|
||||||
|
match constness {
|
||||||
BoundConstness::Never => {}
|
BoundConstness::Never => {}
|
||||||
BoundConstness::Always(span) | BoundConstness::Maybe(span) => {
|
BoundConstness::Always(span) | BoundConstness::Maybe(span) => {
|
||||||
self.dcx().emit_err(errors::ModifierLifetime {
|
return self
|
||||||
span,
|
.dcx()
|
||||||
modifier: modifiers.constness.as_str(),
|
.emit_err(errors::ModifierLifetime { span, modifier: constness.as_str() });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match modifiers.polarity {
|
match polarity {
|
||||||
BoundPolarity::Positive => {}
|
BoundPolarity::Positive => {}
|
||||||
BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => {
|
BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => {
|
||||||
self.dcx().emit_err(errors::ModifierLifetime {
|
return self
|
||||||
span,
|
.dcx()
|
||||||
modifier: modifiers.polarity.as_str(),
|
.emit_err(errors::ModifierLifetime { span, modifier: polarity.as_str() });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match asyncness {
|
||||||
|
BoundAsyncness::Normal => {}
|
||||||
|
BoundAsyncness::Async(span) => {
|
||||||
|
return self
|
||||||
|
.dcx()
|
||||||
|
.emit_err(errors::ModifierLifetime { span, modifier: asyncness.as_str() });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(span) = binder_span {
|
||||||
|
return self.dcx().emit_err(errors::ModifierLifetime { span, modifier: "for<...>" });
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recover on `('lifetime)` with `(` already eaten.
|
/// Recover on `('lifetime)` with `(` already eaten.
|
||||||
fn recover_paren_lifetime(&mut self, lo: Span, inner_lo: Span) -> PResult<'a, ()> {
|
fn recover_paren_lifetime(&mut self, lo: Span, lt_span: Span) -> PResult<'a, ()> {
|
||||||
let inner_span = inner_lo.to(self.prev_token.span);
|
|
||||||
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
|
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
|
||||||
let span = lo.to(self.prev_token.span);
|
let span = lo.to(self.prev_token.span);
|
||||||
let (sugg, snippet) = if let Ok(snippet) = self.span_to_snippet(inner_span) {
|
let (sugg, snippet) = if let Ok(snippet) = self.span_to_snippet(lt_span) {
|
||||||
(Some(span), snippet)
|
(Some(span), snippet)
|
||||||
} else {
|
} else {
|
||||||
(None, String::new())
|
(None, String::new())
|
||||||
|
@ -916,7 +927,7 @@ impl<'a> Parser<'a> {
|
||||||
/// If no modifiers are present, this does not consume any tokens.
|
/// If no modifiers are present, this does not consume any tokens.
|
||||||
///
|
///
|
||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
/// TRAIT_BOUND_MODIFIERS = [["~"] "const"] ["?" | "!"]
|
/// TRAIT_BOUND_MODIFIERS = [["~"] "const"] ["async"] ["?" | "!"]
|
||||||
/// ```
|
/// ```
|
||||||
fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
|
fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
|
||||||
let constness = if self.eat(&token::Tilde) {
|
let constness = if self.eat(&token::Tilde) {
|
||||||
|
@ -970,15 +981,23 @@ impl<'a> Parser<'a> {
|
||||||
/// TY_BOUND_NOPAREN = [TRAIT_BOUND_MODIFIERS] [for<LT_PARAM_DEFS>] SIMPLE_PATH
|
/// TY_BOUND_NOPAREN = [TRAIT_BOUND_MODIFIERS] [for<LT_PARAM_DEFS>] SIMPLE_PATH
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// For example, this grammar accepts `~const ?for<'a: 'b> m::Trait<'a>`.
|
/// For example, this grammar accepts `for<'a: 'b> ~const ?m::Trait<'a>`.
|
||||||
fn parse_generic_ty_bound(
|
fn parse_generic_ty_bound(
|
||||||
&mut self,
|
&mut self,
|
||||||
lo: Span,
|
lo: Span,
|
||||||
has_parens: bool,
|
has_parens: bool,
|
||||||
modifiers: TraitBoundModifiers,
|
|
||||||
leading_token: &Token,
|
leading_token: &Token,
|
||||||
) -> PResult<'a, GenericBound> {
|
) -> PResult<'a, GenericBound> {
|
||||||
let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?;
|
let modifiers = self.parse_trait_bound_modifiers()?;
|
||||||
|
let (mut lifetime_defs, binder_span) = self.parse_late_bound_lifetime_defs()?;
|
||||||
|
|
||||||
|
// Recover erroneous lifetime bound with modifiers or binder.
|
||||||
|
// e.g. `T: for<'a> 'a` or `T: ~const 'a`.
|
||||||
|
if self.token.is_lifetime() {
|
||||||
|
let _: ErrorGuaranteed = self.error_lt_bound_with_modifiers(modifiers, binder_span);
|
||||||
|
return self.parse_generic_lt_bound(lo, has_parens);
|
||||||
|
}
|
||||||
|
|
||||||
let mut path = if self.token.is_keyword(kw::Fn)
|
let mut path = if self.token.is_keyword(kw::Fn)
|
||||||
&& self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis))
|
&& self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis))
|
||||||
&& let Some(path) = self.recover_path_from_fn()
|
&& let Some(path) = self.recover_path_from_fn()
|
||||||
|
@ -1094,16 +1113,19 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Optionally parses `for<$generic_params>`.
|
/// Optionally parses `for<$generic_params>`.
|
||||||
pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, ThinVec<GenericParam>> {
|
pub(super) fn parse_late_bound_lifetime_defs(
|
||||||
|
&mut self,
|
||||||
|
) -> PResult<'a, (ThinVec<GenericParam>, Option<Span>)> {
|
||||||
if self.eat_keyword(kw::For) {
|
if self.eat_keyword(kw::For) {
|
||||||
|
let lo = self.token.span;
|
||||||
self.expect_lt()?;
|
self.expect_lt()?;
|
||||||
let params = self.parse_generic_params()?;
|
let params = self.parse_generic_params()?;
|
||||||
self.expect_gt()?;
|
self.expect_gt()?;
|
||||||
// We rely on AST validation to rule out invalid cases: There must not be type
|
// We rely on AST validation to rule out invalid cases: There must not be
|
||||||
// parameters, and the lifetime parameters must not have bounds.
|
// type or const parameters, and parameters must not have bounds.
|
||||||
Ok(params)
|
Ok((params, Some(lo.to(self.prev_token.span))))
|
||||||
} else {
|
} else {
|
||||||
Ok(ThinVec::new())
|
Ok((ThinVec::new(), None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
tests/ui/higher-ranked/erroneous-lifetime-bound.rs
Normal file
5
tests/ui/higher-ranked/erroneous-lifetime-bound.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
fn foo<T>() where T: for<'a> 'a {}
|
||||||
|
//~^ ERROR `for<...>` may only modify trait bounds, not lifetime bounds
|
||||||
|
//~| ERROR use of undeclared lifetime name `'a` [E0261]
|
||||||
|
|
||||||
|
fn main() {}
|
25
tests/ui/higher-ranked/erroneous-lifetime-bound.stderr
Normal file
25
tests/ui/higher-ranked/erroneous-lifetime-bound.stderr
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
error: `for<...>` may only modify trait bounds, not lifetime bounds
|
||||||
|
--> $DIR/erroneous-lifetime-bound.rs:1:25
|
||||||
|
|
|
||||||
|
LL | fn foo<T>() where T: for<'a> 'a {}
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error[E0261]: use of undeclared lifetime name `'a`
|
||||||
|
--> $DIR/erroneous-lifetime-bound.rs:1:30
|
||||||
|
|
|
||||||
|
LL | fn foo<T>() where T: for<'a> 'a {}
|
||||||
|
| ^^ undeclared lifetime
|
||||||
|
|
|
||||||
|
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||||
|
help: consider making the bound lifetime-generic with a new `'a` lifetime
|
||||||
|
|
|
||||||
|
LL | fn foo<T>() where for<'a> T: for<'a> 'a {}
|
||||||
|
| +++++++
|
||||||
|
help: consider introducing lifetime `'a` here
|
||||||
|
|
|
||||||
|
LL | fn foo<'a, T>() where T: for<'a> 'a {}
|
||||||
|
| +++
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0261`.
|
25
tests/ui/impl-trait/precise-capturing/bound-modifiers.rs
Normal file
25
tests/ui/impl-trait/precise-capturing/bound-modifiers.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
//@ edition: 2021
|
||||||
|
|
||||||
|
#![feature(precise_capturing)]
|
||||||
|
|
||||||
|
fn polarity() -> impl Sized + ?use<> {}
|
||||||
|
//~^ ERROR expected identifier, found keyword `use`
|
||||||
|
//~| ERROR cannot find trait `r#use` in this scope
|
||||||
|
//~| WARN relaxing a default bound only does something for `?Sized`
|
||||||
|
//~| WARN relaxing a default bound only does something for `?Sized`
|
||||||
|
|
||||||
|
fn asyncness() -> impl Sized + async use<> {}
|
||||||
|
//~^ ERROR expected identifier, found keyword `use`
|
||||||
|
//~| ERROR cannot find trait `r#use` in this scope
|
||||||
|
//~| ERROR async closures are unstable
|
||||||
|
|
||||||
|
fn constness() -> impl Sized + const use<> {}
|
||||||
|
//~^ ERROR expected identifier, found keyword `use`
|
||||||
|
//~| ERROR cannot find trait `r#use` in this scope
|
||||||
|
//~| ERROR const trait impls are experimental
|
||||||
|
|
||||||
|
fn binder() -> impl Sized + for<'a> use<> {}
|
||||||
|
//~^ ERROR expected identifier, found keyword `use`
|
||||||
|
//~| ERROR cannot find trait `r#use` in this scope
|
||||||
|
|
||||||
|
fn main() {}
|
87
tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr
Normal file
87
tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
error: expected identifier, found keyword `use`
|
||||||
|
--> $DIR/bound-modifiers.rs:5:32
|
||||||
|
|
|
||||||
|
LL | fn polarity() -> impl Sized + ?use<> {}
|
||||||
|
| ^^^ expected identifier, found keyword
|
||||||
|
|
||||||
|
error: expected identifier, found keyword `use`
|
||||||
|
--> $DIR/bound-modifiers.rs:11:38
|
||||||
|
|
|
||||||
|
LL | fn asyncness() -> impl Sized + async use<> {}
|
||||||
|
| ^^^ expected identifier, found keyword
|
||||||
|
|
||||||
|
error: expected identifier, found keyword `use`
|
||||||
|
--> $DIR/bound-modifiers.rs:16:38
|
||||||
|
|
|
||||||
|
LL | fn constness() -> impl Sized + const use<> {}
|
||||||
|
| ^^^ expected identifier, found keyword
|
||||||
|
|
||||||
|
error: expected identifier, found keyword `use`
|
||||||
|
--> $DIR/bound-modifiers.rs:21:37
|
||||||
|
|
|
||||||
|
LL | fn binder() -> impl Sized + for<'a> use<> {}
|
||||||
|
| ^^^ expected identifier, found keyword
|
||||||
|
|
||||||
|
error[E0405]: cannot find trait `r#use` in this scope
|
||||||
|
--> $DIR/bound-modifiers.rs:5:32
|
||||||
|
|
|
||||||
|
LL | fn polarity() -> impl Sized + ?use<> {}
|
||||||
|
| ^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0405]: cannot find trait `r#use` in this scope
|
||||||
|
--> $DIR/bound-modifiers.rs:11:38
|
||||||
|
|
|
||||||
|
LL | fn asyncness() -> impl Sized + async use<> {}
|
||||||
|
| ^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0405]: cannot find trait `r#use` in this scope
|
||||||
|
--> $DIR/bound-modifiers.rs:16:38
|
||||||
|
|
|
||||||
|
LL | fn constness() -> impl Sized + const use<> {}
|
||||||
|
| ^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0405]: cannot find trait `r#use` in this scope
|
||||||
|
--> $DIR/bound-modifiers.rs:21:37
|
||||||
|
|
|
||||||
|
LL | fn binder() -> impl Sized + for<'a> use<> {}
|
||||||
|
| ^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0658]: async closures are unstable
|
||||||
|
--> $DIR/bound-modifiers.rs:11:32
|
||||||
|
|
|
||||||
|
LL | fn asyncness() -> impl Sized + async use<> {}
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
|
||||||
|
= help: add `#![feature(async_closure)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
= help: to use an async block, remove the `||`: `async {`
|
||||||
|
|
||||||
|
error[E0658]: const trait impls are experimental
|
||||||
|
--> $DIR/bound-modifiers.rs:16:32
|
||||||
|
|
|
||||||
|
LL | fn constness() -> impl Sized + const use<> {}
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
|
||||||
|
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
|
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
|
--> $DIR/bound-modifiers.rs:5:31
|
||||||
|
|
|
||||||
|
LL | fn polarity() -> impl Sized + ?use<> {}
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
|
--> $DIR/bound-modifiers.rs:5:31
|
||||||
|
|
|
||||||
|
LL | fn polarity() -> impl Sized + ?use<> {}
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||||
|
|
||||||
|
error: aborting due to 10 previous errors; 2 warnings emitted
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0405, E0658.
|
||||||
|
For more information about an error, try `rustc --explain E0405`.
|
Loading…
Add table
Add a link
Reference in a new issue