diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index ce76c2cba939c..f70b097c26fec 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -273,7 +273,7 @@ fn configure_and_expand( // Done with macro expansion! - resolver.resolve_crate(&krate); + resolver.resolve_crate(&mut krate); krate } diff --git a/compiler/rustc_resolve/src/desugar.rs b/compiler/rustc_resolve/src/desugar.rs new file mode 100644 index 0000000000000..902f7c7f8cd63 --- /dev/null +++ b/compiler/rustc_resolve/src/desugar.rs @@ -0,0 +1,57 @@ +use rustc_ast::{ + mut_visit::{self, MutVisitor}, + ptr::P, + Path, TraitObjectSyntax, Ty, TyKind, +}; +use rustc_hir::def::DefKind; + +use crate::{Res, Resolver}; + +struct LateDesugarVisitor<'a, 'b, 'tcx> { + r: &'b mut Resolver<'a, 'tcx>, +} + +impl<'a, 'b, 'tcx> LateDesugarVisitor<'a, 'b, 'tcx> { + fn new(resolver: &'b mut Resolver<'a, 'tcx>) -> Self { + LateDesugarVisitor { r: resolver } + } +} + +impl MutVisitor for LateDesugarVisitor<'_, '_, '_> { + fn visit_ty(&mut self, ty: &mut P) { + // If the type is a path, and that path resolves to a trate, desugar it + // into a bare trait object. + + if let TyKind::Path(None, _path) = &ty.kind + && let Some(partial_res) = self.r.partial_res_map.get(&ty.id) + && let Some(res @ Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = + partial_res.full_res() + { + debug!("[Desugar][Ty][BareTrait][{:?}] {:?}\n{:#?}", ty.span, res, ty); + + // TODO(axelmagn): extract bounds from path? + let bounds = vec![]; + // TODO(axelmagn): is this the right choice? I don't think a trait + // path would ever imply Dyn, so None is the only other option. + let syntax = TraitObjectSyntax::None; + let trait_obj = TyKind::TraitObject(bounds, syntax); + ty.kind = trait_obj; + + // TODO(axelmagn): Do the type tokens need to be rewritten? I would + // assume so, for use in AST lowering. + + debug!("->\n{:#?}\n", ty); + } + + mut_visit::noop_visit_ty(ty, self); + } + + fn visit_path(&mut self, path: &mut Path) { + // TODO(axelmagn): Desugar type-relative paths during resolution. + // Transform a::b::c::d to ::d when a::b::c can be resolved to + // a type and ::d cannot (for instance because it is a trait method). + // (check rustc_ast_lowering::path::lower_qpath for current impl) + + mut_visit::noop_visit_path(path, self); + } +} diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index a82f7bdfbf3fd..8208e8ef3882b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -12,6 +12,7 @@ use crate::{path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeB use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; +use rustc_ast::mut_visit::MutVisitor; use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; @@ -669,7 +670,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// State used to know whether to ignore resolution errors for function bodies. /// /// In particular, rustdoc uses this to avoid giving errors for `cfg()` items. - /// In most cases this will be `None`, in which case errors will always be reported. + /// In most cases this will be `false`, in which case errors will always be reported. /// If it is `true`, then it will be updated when entering a nested function or trait body. in_func_body: bool, @@ -4592,13 +4593,26 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> { } impl<'a, 'tcx> Resolver<'a, 'tcx> { - pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) { + pub(crate) fn late_resolve_crate(&mut self, krate: &mut Crate) { visit::walk_crate(&mut LifetimeCountVisitor { r: self }, krate); - let mut late_resolution_visitor = LateResolutionVisitor::new(self); - late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); - visit::walk_crate(&mut late_resolution_visitor, krate); - for (id, span) in late_resolution_visitor.diagnostic_metadata.unused_labels.iter() { - self.lint_buffer.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label"); + { + let mut late_resolution_visitor = LateResolutionVisitor::new(self); + late_resolution_visitor + .resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); + visit::walk_crate(&mut late_resolution_visitor, krate); + for (id, span) in late_resolution_visitor.diagnostic_metadata.unused_labels.iter() { + self.lint_buffer.buffer_lint( + lint::builtin::UNUSED_LABELS, + *id, + *span, + "unused label", + ); + } + } + + { + let mut late_desugar_visitor = LateDesugarVisitor::new(self); + late_desugar_visitor.visit_crate(krate); } } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index a14f3d494fb4d..ca61c0bf0b977 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -77,6 +77,7 @@ type Res = def::Res; mod build_reduced_graph; mod check_unused; mod def_collector; +mod desugar; mod diagnostics; mod effective_visibilities; mod errors; @@ -1591,7 +1592,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } /// Entry point to crate resolution. - pub fn resolve_crate(&mut self, krate: &Crate) { + pub fn resolve_crate(&mut self, krate: &mut Crate) { self.tcx.sess.time("resolve_crate", || { self.tcx.sess.time("finalize_imports", || self.finalize_imports()); let exported_ambiguities = self.tcx.sess.time("compute_effective_visibilities", || {