Auto merge of #82868 - petrochenkov:bto, r=estebank

Report missing cases of `bare_trait_objects`

Fixes https://github.com/rust-lang/rust/issues/65371
This commit is contained in:
bors 2021-03-18 05:27:26 +00:00
commit 2aafe452b8
39 changed files with 192 additions and 93 deletions

View file

@ -1477,7 +1477,7 @@ impl Clean<Type> for hir::Ty<'_> {
}
}
TyKind::Path(_) => clean_qpath(&self, cx),
TyKind::TraitObject(ref bounds, ref lifetime) => {
TyKind::TraitObject(ref bounds, ref lifetime, _) => {
match bounds[0].clean(cx).trait_ {
ResolvedPath { path, param_names: None, did, is_generic } => {
let mut bounds: Vec<self::GenericBound> = bounds[1..]

View file

@ -0,0 +1,18 @@
#![feature(associated_type_defaults)]
trait Assoc {
fn func() {}
const CONST: u8 = 0;
type Ty = u8;
}
trait Dyn {}
impl Assoc for dyn Dyn {}
fn main() {
Dyn::func(); //~ WARN trait objects without an explicit `dyn` are deprecated
::Dyn::func(); //~ WARN trait objects without an explicit `dyn` are deprecated
Dyn::CONST; //~ WARN trait objects without an explicit `dyn` are deprecated
let _: Dyn::Ty; //~ ERROR ambiguous associated type
}

View file

@ -0,0 +1,29 @@
error[E0223]: ambiguous associated type
--> $DIR/bare-trait-objects-path.rs:17:12
|
LL | let _: Dyn::Ty;
| ^^^^^^^ help: use fully-qualified syntax: `<dyn Dyn as Trait>::Ty`
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/bare-trait-objects-path.rs:14:5
|
LL | Dyn::func();
| ^^^ help: use `dyn`: `<dyn Dyn>`
|
= note: `#[warn(bare_trait_objects)]` on by default
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/bare-trait-objects-path.rs:15:5
|
LL | ::Dyn::func();
| ^^^^^ help: use `dyn`: `<dyn (::Dyn)>`
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/bare-trait-objects-path.rs:16:5
|
LL | Dyn::CONST;
| ^^^ help: use `dyn`: `<dyn Dyn>`
error: aborting due to previous error; 3 warnings emitted
For more information about this error, try `rustc --explain E0223`.

View file

@ -30,8 +30,8 @@ fn main() {
let x: &dyn T = &42;
x.foo();
T::foo(x);
T::bar();
<dyn T>::foo(x);
<dyn T>::bar();
unsafe { assert_eq!(COUNT, 12); }

View file

@ -31,7 +31,7 @@ fn with_trait<C:CompareToInts>(c: &C) -> bool {
}
fn with_ufcs1<C:CompareToInts>(c: &C) -> bool {
CompareToInts::same_as(c, 22) //~ ERROR `dyn CompareToInts: CompareTo<i32>` is not satisfied
<dyn CompareToInts>::same_as(c, 22) //~ ERROR `dyn CompareToInts: CompareTo<i32>` is not satisfi
}
fn with_ufcs2<C:CompareToInts>(c: &C) -> bool {

View file

@ -21,8 +21,8 @@ error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfi
LL | fn same_as(&self, t: T) -> bool;
| -------------------------------- required by `CompareTo::same_as`
...
LL | CompareToInts::same_as(c, 22)
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
LL | <dyn CompareToInts>::same_as(c, 22)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied
--> $DIR/repeated-supertrait-ambig.rs:38:5

View file

@ -31,7 +31,7 @@ fn with_trait<C:CompareToInts>(c: &C) -> bool {
}
fn with_ufcs1<C:CompareToInts>(c: &C) -> bool {
CompareToInts::same_as(c, 22_i64) && CompareToInts::same_as(c, 22_u64)
<dyn CompareToInts>::same_as(c, 22_i64) && <dyn CompareToInts>::same_as(c, 22_u64)
}
fn with_ufcs2<C:CompareToInts>(c: &C) -> bool {

View file

@ -81,8 +81,8 @@ fn check_method() {
//~^ ERROR no function or associated item named `b` found
S::c(&S); // OK
// a, b, c are resolved as inherent items, their traits don't need to be in scope
C::a(&S); //~ ERROR associated function `a` is private
C::b(&S); // OK
<dyn C>::a(&S); //~ ERROR associated function `a` is private
<dyn C>::b(&S); // OK
C::c(&S); // OK
}
@ -98,9 +98,9 @@ fn check_assoc_const() {
S::B; //~ ERROR no associated item named `B` found
S::C; // OK
// A, B, C are resolved as inherent items, their traits don't need to be in scope
C::A; //~ ERROR associated constant `A` is private
//~^ ERROR the trait `assoc_const::C` cannot be made into an object
C::B; // ERROR the trait `assoc_const::C` cannot be made into an object
<dyn C>::A; //~ ERROR associated constant `A` is private
//~^ ERROR the trait `assoc_const::C` cannot be made into an object
<dyn C>::B; // ERROR the trait `assoc_const::C` cannot be made into an object
C::C; // OK
}

View file

@ -67,10 +67,10 @@ LL | use method::B;
|
error[E0624]: associated function `a` is private
--> $DIR/item-privacy.rs:84:8
--> $DIR/item-privacy.rs:84:14
|
LL | C::a(&S);
| ^ private associated function
LL | <dyn C>::a(&S);
| ^ private associated function
error[E0599]: no associated item named `A` found for struct `S` in the current scope
--> $DIR/item-privacy.rs:97:8
@ -104,16 +104,16 @@ LL | use assoc_const::B;
|
error[E0624]: associated constant `A` is private
--> $DIR/item-privacy.rs:101:8
--> $DIR/item-privacy.rs:101:14
|
LL | C::A;
| ^ private associated constant
LL | <dyn C>::A;
| ^ private associated constant
error[E0038]: the trait `assoc_const::C` cannot be made into an object
--> $DIR/item-privacy.rs:101:5
--> $DIR/item-privacy.rs:101:6
|
LL | C::A;
| ^ `assoc_const::C` cannot be made into an object
LL | <dyn C>::A;
| ^^^^^ `assoc_const::C` cannot be made into an object
|
= help: consider moving `C` to another trait
= help: consider moving `B` to another trait

View file

@ -387,7 +387,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
self.nested_elision_site_lts.append(&mut sub_visitor.all_lts());
return;
},
TyKind::TraitObject(bounds, ref lt) => {
TyKind::TraitObject(bounds, ref lt, _) => {
if !lt.is_elided() {
self.unelided_trait_object_lifetime = true;
}

View file

@ -50,7 +50,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
// Originally reported as the issue #3128.
let inner_snippet = snippet(cx, inner.span, "..");
let suggestion = match &inner.kind {
TyKind::TraitObject(bounds, lt_bound) if bounds.len() > 1 || !lt_bound.is_elided() => {
TyKind::TraitObject(bounds, lt_bound, _) if bounds.len() > 1 || !lt_bound.is_elided() => {
format!("&{}({})", ltopt, &inner_snippet)
},
TyKind::Path(qpath)
@ -86,7 +86,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
// Returns true if given type is `Any` trait.
fn is_any_trait(t: &hir::Ty<'_>) -> bool {
if_chain! {
if let TyKind::TraitObject(ref traits, _) = t.kind;
if let TyKind::TraitObject(ref traits, ..) = t.kind;
if !traits.is_empty();
// Only Send/Sync can be used as additional traits, so it is enough to
// check only the first trait.

View file

@ -911,7 +911,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
// function types bring a lot of overhead
TyKind::BareFn(ref bare) if bare.abi == Abi::Rust => (50 * self.nest, 1),
TyKind::TraitObject(ref param_bounds, _) => {
TyKind::TraitObject(ref param_bounds, ..) => {
let has_lifetime_parameters = param_bounds.iter().any(|bound| {
bound
.bound_generic_params

View file

@ -892,7 +892,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
TyKind::OpaqueDef(_, arg_list) => {
self.hash_generic_args(arg_list);
},
TyKind::TraitObject(_, lifetime) => {
TyKind::TraitObject(_, lifetime, _) => {
self.hash_lifetime(lifetime);
},
TyKind::Typeof(anon_const) => {