Skip to content

Commit 7a626cf

Browse files
authored
Rollup merge of #89090 - cjgillot:bare-dyn, r=jackh726
Lint bare traits in AstConv. Removing the lint from lowering allows to: - make lowering querification easier; - have the lint implementation in only one place. r? `@estebank`
2 parents 54e7946 + 6fcbc3a commit 7a626cf

File tree

51 files changed

+731
-320
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+731
-320
lines changed

compiler/rustc_ast_lowering/src/lib.rs

+3-45
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use rustc_data_structures::fx::FxHashSet;
4646
use rustc_data_structures::sorted_map::SortedMap;
4747
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
4848
use rustc_data_structures::sync::Lrc;
49-
use rustc_errors::{struct_span_err, Applicability};
49+
use rustc_errors::struct_span_err;
5050
use rustc_hir as hir;
5151
use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
5252
use rustc_hir::def_id::{DefId, DefPathHash, LocalDefId, CRATE_DEF_ID};
@@ -55,11 +55,9 @@ use rustc_hir::intravisit;
5555
use rustc_hir::{ConstArg, GenericArg, ParamName};
5656
use rustc_index::vec::{Idx, IndexVec};
5757
use rustc_query_system::ich::StableHashingContext;
58-
use rustc_session::lint::builtin::BARE_TRAIT_OBJECTS;
59-
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
58+
use rustc_session::lint::LintBuffer;
6059
use rustc_session::utils::{FlattenNonterminals, NtToTokenstream};
6160
use rustc_session::Session;
62-
use rustc_span::edition::Edition;
6361
use rustc_span::hygiene::ExpnId;
6462
use rustc_span::source_map::{respan, DesugaringKind};
6563
use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -1184,11 +1182,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
11841182
) -> hir::Ty<'hir> {
11851183
let id = self.lower_node_id(t.id);
11861184
let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx);
1187-
let ty = self.ty_path(id, t.span, qpath);
1188-
if let hir::TyKind::TraitObject(..) = ty.kind {
1189-
self.maybe_lint_bare_trait(t.span, t.id, qself.is_none() && path.is_global());
1190-
}
1191-
ty
1185+
self.ty_path(id, t.span, qpath)
11921186
}
11931187

11941188
fn ty(&mut self, span: Span, kind: hir::TyKind<'hir>) -> hir::Ty<'hir> {
@@ -1285,9 +1279,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12851279
lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span));
12861280
(bounds, lifetime_bound)
12871281
});
1288-
if kind != TraitObjectSyntax::Dyn {
1289-
self.maybe_lint_bare_trait(t.span, t.id, false);
1290-
}
12911282
hir::TyKind::TraitObject(bounds, lifetime_bound, kind)
12921283
}
12931284
TyKind::ImplTrait(def_node_id, ref bounds) => {
@@ -2380,39 +2371,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23802371
name: hir::LifetimeName::Implicit(missing),
23812372
}
23822373
}
2383-
2384-
fn maybe_lint_bare_trait(&mut self, span: Span, id: NodeId, is_global: bool) {
2385-
// FIXME(davidtwco): This is a hack to detect macros which produce spans of the
2386-
// call site which do not have a macro backtrace. See #61963.
2387-
let is_macro_callsite = self
2388-
.sess
2389-
.source_map()
2390-
.span_to_snippet(span)
2391-
.map(|snippet| snippet.starts_with("#["))
2392-
.unwrap_or(true);
2393-
if !is_macro_callsite {
2394-
if span.edition() < Edition::Edition2021 {
2395-
self.resolver.lint_buffer().buffer_lint_with_diagnostic(
2396-
BARE_TRAIT_OBJECTS,
2397-
id,
2398-
span,
2399-
"trait objects without an explicit `dyn` are deprecated",
2400-
BuiltinLintDiagnostics::BareTraitObject(span, is_global),
2401-
)
2402-
} else {
2403-
let msg = "trait objects must include the `dyn` keyword";
2404-
let label = "add `dyn` keyword before this trait";
2405-
let mut err = struct_span_err!(self.sess, span, E0782, "{}", msg,);
2406-
err.span_suggestion_verbose(
2407-
span.shrink_to_lo(),
2408-
label,
2409-
String::from("dyn "),
2410-
Applicability::MachineApplicable,
2411-
);
2412-
err.emit();
2413-
}
2414-
}
2415-
}
24162374
}
24172375

24182376
/// Helper struct for delayed construction of GenericArgs.

compiler/rustc_lint/src/context.rs

-10
Original file line numberDiff line numberDiff line change
@@ -633,16 +633,6 @@ pub trait LintContext: Sized {
633633
}
634634
},
635635
BuiltinLintDiagnostics::Normal => (),
636-
BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
637-
let (sugg, app) = match sess.source_map().span_to_snippet(span) {
638-
Ok(s) if is_global => {
639-
(format!("dyn ({})", s), Applicability::MachineApplicable)
640-
}
641-
Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable),
642-
Err(_) => ("dyn <type>".to_string(), Applicability::HasPlaceholders),
643-
};
644-
db.span_suggestion(span, "use `dyn`", sugg, app);
645-
}
646636
BuiltinLintDiagnostics::AbsPathWithModule(span) => {
647637
let (sugg, app) = match sess.source_map().span_to_snippet(span) {
648638
Ok(ref s) => {

compiler/rustc_lint_defs/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,6 @@ pub enum ExternDepSpec {
285285
#[derive(PartialEq, Debug)]
286286
pub enum BuiltinLintDiagnostics {
287287
Normal,
288-
BareTraitObject(Span, /* is_global */ bool),
289288
AbsPathWithModule(Span),
290289
ProcMacroDeriveResolutionFallback(Span),
291290
MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),

compiler/rustc_typeck/src/astconv/mod.rs

+72-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::errors::{
1313
};
1414
use crate::middle::resolve_lifetime as rl;
1515
use crate::require_c_abi_if_c_variadic;
16+
use rustc_ast::TraitObjectSyntax;
1617
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1718
use rustc_errors::{struct_span_err, Applicability, ErrorReported, FatalError};
1819
use rustc_hir as hir;
@@ -24,7 +25,8 @@ use rustc_hir::{GenericArg, GenericArgs};
2425
use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, Subst, SubstsRef};
2526
use rustc_middle::ty::GenericParamDefKind;
2627
use rustc_middle::ty::{self, Const, DefIdTree, Ty, TyCtxt, TypeFoldable};
27-
use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
28+
use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
29+
use rustc_span::edition::Edition;
2830
use rustc_span::lev_distance::find_best_match_for_name;
2931
use rustc_span::symbol::{Ident, Symbol};
3032
use rustc_span::{Span, DUMMY_SP};
@@ -2266,13 +2268,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22662268
/// Parses the programmer's textual representation of a type into our
22672269
/// internal notion of a type.
22682270
pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
2269-
self.ast_ty_to_ty_inner(ast_ty, false)
2271+
self.ast_ty_to_ty_inner(ast_ty, false, false)
2272+
}
2273+
2274+
/// Parses the programmer's textual representation of a type into our
2275+
/// internal notion of a type. This is meant to be used within a path.
2276+
pub fn ast_ty_to_ty_in_path(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
2277+
self.ast_ty_to_ty_inner(ast_ty, false, true)
22702278
}
22712279

22722280
/// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
22732281
/// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
22742282
#[tracing::instrument(level = "debug", skip(self))]
2275-
fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool) -> Ty<'tcx> {
2283+
fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool, in_path: bool) -> Ty<'tcx> {
22762284
let tcx = self.tcx();
22772285

22782286
let result_ty = match ast_ty.kind {
@@ -2283,7 +2291,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22832291
hir::TyKind::Rptr(ref region, ref mt) => {
22842292
let r = self.ast_region_to_region(region, None);
22852293
debug!(?r);
2286-
let t = self.ast_ty_to_ty_inner(mt.ty, true);
2294+
let t = self.ast_ty_to_ty_inner(mt.ty, true, false);
22872295
tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl })
22882296
}
22892297
hir::TyKind::Never => tcx.types.never,
@@ -2302,6 +2310,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23022310
))
23032311
}
23042312
hir::TyKind::TraitObject(bounds, ref lifetime, _) => {
2313+
self.maybe_lint_bare_trait(ast_ty, in_path);
23052314
self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed)
23062315
}
23072316
hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
@@ -2329,7 +2338,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23292338
}
23302339
hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
23312340
debug!(?qself, ?segment);
2332-
let ty = self.ast_ty_to_ty(qself);
2341+
let ty = self.ast_ty_to_ty_inner(qself, false, true);
23332342

23342343
let res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = qself.kind {
23352344
path.res
@@ -2586,4 +2595,62 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
25862595
}
25872596
Some(r)
25882597
}
2598+
2599+
fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) {
2600+
let tcx = self.tcx();
2601+
if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
2602+
self_ty.kind
2603+
{
2604+
let needs_bracket = in_path
2605+
&& !tcx
2606+
.sess
2607+
.source_map()
2608+
.span_to_prev_source(self_ty.span)
2609+
.ok()
2610+
.map_or(false, |s| s.trim_end().ends_with('<'));
2611+
2612+
let is_global = poly_trait_ref.trait_ref.path.is_global();
2613+
let sugg = Vec::from_iter([
2614+
(
2615+
self_ty.span.shrink_to_lo(),
2616+
format!(
2617+
"{}dyn {}",
2618+
if needs_bracket { "<" } else { "" },
2619+
if is_global { "(" } else { "" },
2620+
),
2621+
),
2622+
(
2623+
self_ty.span.shrink_to_hi(),
2624+
format!(
2625+
"{}{}",
2626+
if is_global { ")" } else { "" },
2627+
if needs_bracket { ">" } else { "" },
2628+
),
2629+
),
2630+
]);
2631+
if self_ty.span.edition() >= Edition::Edition2021 {
2632+
let msg = "trait objects must include the `dyn` keyword";
2633+
let label = "add `dyn` keyword before this trait";
2634+
rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg)
2635+
.multipart_suggestion_verbose(label, sugg, Applicability::MachineApplicable)
2636+
.emit();
2637+
} else {
2638+
let msg = "trait objects without an explicit `dyn` are deprecated";
2639+
tcx.struct_span_lint_hir(
2640+
BARE_TRAIT_OBJECTS,
2641+
self_ty.hir_id,
2642+
self_ty.span,
2643+
|lint| {
2644+
lint.build(msg)
2645+
.multipart_suggestion_verbose(
2646+
"use `dyn`",
2647+
sugg,
2648+
Applicability::MachineApplicable,
2649+
)
2650+
.emit()
2651+
},
2652+
);
2653+
}
2654+
}
2655+
}
25892656
}

compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

+2-56
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@ use crate::check::callee::{self, DeferredCallResolution};
66
use crate::check::method::{self, MethodCallee, SelfSource};
77
use crate::check::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy};
88

9-
use rustc_ast::TraitObjectSyntax;
109
use rustc_data_structures::captures::Captures;
1110
use rustc_data_structures::fx::FxHashSet;
1211
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorReported};
1312
use rustc_hir as hir;
1413
use rustc_hir::def::{CtorOf, DefKind, Res};
1514
use rustc_hir::def_id::DefId;
1615
use rustc_hir::lang_items::LangItem;
17-
use rustc_hir::{ExprKind, GenericArg, Node, QPath, TyKind};
16+
use rustc_hir::{ExprKind, GenericArg, Node, QPath};
1817
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
1918
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
2019
use rustc_infer::infer::{InferOk, InferResult};
@@ -28,8 +27,6 @@ use rustc_middle::ty::{
2827
Ty, UserType,
2928
};
3029
use rustc_session::lint;
31-
use rustc_session::lint::builtin::BARE_TRAIT_OBJECTS;
32-
use rustc_span::edition::Edition;
3330
use rustc_span::hygiene::DesugaringKind;
3431
use rustc_span::source_map::{original_sp, DUMMY_SP};
3532
use rustc_span::symbol::{kw, sym, Ident};
@@ -855,7 +852,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
855852
// to be object-safe.
856853
// We manually call `register_wf_obligation` in the success path
857854
// below.
858-
(<dyn AstConv<'_>>::ast_ty_to_ty(self, qself), qself, segment)
855+
(<dyn AstConv<'_>>::ast_ty_to_ty_in_path(self, qself), qself, segment)
859856
}
860857
QPath::LangItem(..) => {
861858
bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
@@ -901,7 +898,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
901898
});
902899

903900
if result.is_ok() {
904-
self.maybe_lint_bare_trait(qpath, hir_id, span);
905901
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
906902
}
907903

@@ -914,56 +910,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
914910
)
915911
}
916912

917-
fn maybe_lint_bare_trait(&self, qpath: &QPath<'_>, hir_id: hir::HirId, span: Span) {
918-
if let QPath::TypeRelative(self_ty, _) = qpath {
919-
if let TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
920-
self_ty.kind
921-
{
922-
let msg = "trait objects without an explicit `dyn` are deprecated";
923-
let (sugg, app) = match self.tcx.sess.source_map().span_to_snippet(self_ty.span) {
924-
Ok(s) if poly_trait_ref.trait_ref.path.is_global() => {
925-
(format!("dyn ({})", s), Applicability::MachineApplicable)
926-
}
927-
Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable),
928-
Err(_) => ("dyn <type>".to_string(), Applicability::HasPlaceholders),
929-
};
930-
// Wrap in `<..>` if it isn't already.
931-
let sugg = match self.tcx.sess.source_map().span_to_snippet(span) {
932-
Ok(s) if s.starts_with('<') => sugg,
933-
_ => format!("<{}>", sugg),
934-
};
935-
let sugg_label = "use `dyn`";
936-
if self.sess().edition() >= Edition::Edition2021 {
937-
let mut err = rustc_errors::struct_span_err!(
938-
self.sess(),
939-
self_ty.span,
940-
E0782,
941-
"{}",
942-
msg,
943-
);
944-
err.span_suggestion(
945-
self_ty.span,
946-
sugg_label,
947-
sugg,
948-
Applicability::MachineApplicable,
949-
)
950-
.emit();
951-
} else {
952-
self.tcx.struct_span_lint_hir(
953-
BARE_TRAIT_OBJECTS,
954-
hir_id,
955-
self_ty.span,
956-
|lint| {
957-
let mut db = lint.build(msg);
958-
db.span_suggestion(self_ty.span, sugg_label, sugg, app);
959-
db.emit()
960-
},
961-
);
962-
}
963-
}
964-
}
965-
}
966-
967913
/// Given a function `Node`, return its `FnDecl` if it exists, or `None` otherwise.
968914
pub(in super::super) fn get_node_fn_decl(
969915
&self,

src/test/rustdoc-ui/display-output.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
/// #![warn(unused)]
1111
/// let x = 12;
1212
///
13-
/// fn foo(x: &std::fmt::Display) {}
13+
/// fn foo(x: &dyn std::fmt::Display) {}
1414
/// ```
1515
pub fn foo() {}

src/test/rustdoc-ui/display-output.stdout

+3-13
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,6 @@ test $DIR/display-output.rs - foo (line 9) ... ok
55
successes:
66

77
---- $DIR/display-output.rs - foo (line 9) stdout ----
8-
warning: trait objects without an explicit `dyn` are deprecated
9-
--> $DIR/display-output.rs:13:12
10-
|
11-
LL | fn foo(x: &std::fmt::Display) {}
12-
| ^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn std::fmt::Display`
13-
|
14-
= note: `#[warn(bare_trait_objects)]` on by default
15-
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
16-
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
17-
188
warning: unused variable: `x`
199
--> $DIR/display-output.rs:11:5
2010
|
@@ -31,13 +21,13 @@ LL | #![warn(unused)]
3121
warning: unused variable: `x`
3222
--> $DIR/display-output.rs:13:8
3323
|
34-
LL | fn foo(x: &std::fmt::Display) {}
24+
LL | fn foo(x: &dyn std::fmt::Display) {}
3525
| ^ help: if this is intentional, prefix it with an underscore: `_x`
3626

3727
warning: function is never used: `foo`
3828
--> $DIR/display-output.rs:13:4
3929
|
40-
LL | fn foo(x: &std::fmt::Display) {}
30+
LL | fn foo(x: &dyn std::fmt::Display) {}
4131
| ^^^
4232
|
4333
note: the lint level is defined here
@@ -47,7 +37,7 @@ LL | #![warn(unused)]
4737
| ^^^^^^
4838
= note: `#[warn(dead_code)]` implied by `#[warn(unused)]`
4939

50-
warning: 4 warnings emitted
40+
warning: 3 warnings emitted
5141

5242

5343

src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs

-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ fn b() {
1212
//~^ ERROR expected trait, found constant `BAR`
1313
//~| ERROR expected trait, found constant `BAR`
1414
//~| ERROR type provided when a constant was expected
15-
//~| WARN trait objects without an explicit `dyn` are deprecated
16-
//~| WARN this is accepted in the current edition
1715
}
1816
fn c() {
1917
foo::<3 + 3>(); //~ ERROR expressions must be enclosed in braces

0 commit comments

Comments
 (0)