1
Fork 0

Remove support for compiler plugins.

They've been deprecated for four years.

This commit includes the following changes.
- It eliminates the `rustc_plugin_impl` crate.
- It changes the language used for lints in
  `compiler/rustc_driver_impl/src/lib.rs` and
  `compiler/rustc_lint/src/context.rs`. External lints are now called
  "loaded" lints, rather than "plugins" to avoid confusion with the old
  plugins. This only has a tiny effect on the output of `-W help`.
- E0457 and E0498 are no longer used.
- E0463 is narrowed, now only relating to unfound crates, not plugins.
- The `plugin` feature was moved from "active" to "removed".
- It removes the entire plugins chapter from the unstable book.
- It removes quite a few tests, mostly all of those in
  `tests/ui-fulldeps/plugin/`.

Closes #29597.
This commit is contained in:
Nicholas Nethercote 2023-10-03 13:54:17 +11:00
parent ab161d1f5d
commit 5c462a32bd
101 changed files with 57 additions and 1712 deletions

View file

@ -68,7 +68,6 @@ rm -r tests/run-make/split-debuginfo # same
rm -r tests/run-make/symbols-include-type-name # --emit=asm not supported
rm -r tests/run-make/target-specs # i686 not supported by Cranelift
rm -r tests/run-make/mismatching-target-triples # same
rm -r tests/run-make/use-extern-for-plugins # same
rm tests/ui/asm/x86_64/issue-82869.rs # vector regs in inline asm not yet supported
rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly

View file

@ -39,7 +39,6 @@ rustc_mir_transform = { path = "../rustc_mir_transform" }
rustc_monomorphize = { path = "../rustc_monomorphize" }
rustc_parse = { path = "../rustc_parse" }
rustc_passes = { path = "../rustc_passes" }
rustc_plugin_impl = { path = "../rustc_plugin_impl" }
rustc_privacy = { path = "../rustc_privacy" }
rustc_query_system = { path = "../rustc_query_system" }
rustc_resolve = { path = "../rustc_resolve" }

View file

@ -20,8 +20,6 @@
#[macro_use]
extern crate tracing;
pub extern crate rustc_plugin_impl as plugin;
use rustc_ast as ast;
use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
use rustc_data_structures::profiling::{
@ -132,7 +130,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[
rustc_monomorphize::DEFAULT_LOCALE_RESOURCE,
rustc_parse::DEFAULT_LOCALE_RESOURCE,
rustc_passes::DEFAULT_LOCALE_RESOURCE,
rustc_plugin_impl::DEFAULT_LOCALE_RESOURCE,
rustc_privacy::DEFAULT_LOCALE_RESOURCE,
rustc_query_system::DEFAULT_LOCALE_RESOURCE,
rustc_resolve::DEFAULT_LOCALE_RESOURCE,
@ -994,16 +991,14 @@ the command line flag directly.
}
/// Write to stdout lint command options, together with a list of all available lints
pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) {
pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_lints: bool) {
safe_println!(
"
Available lint options:
-W <foo> Warn about <foo>
-A <foo> \
Allow <foo>
-A <foo> Allow <foo>
-D <foo> Deny <foo>
-F <foo> Forbid <foo> \
(deny <foo> and all attempts to override)
-F <foo> Forbid <foo> (deny <foo> and all attempts to override)
"
);
@ -1022,18 +1017,18 @@ Available lint options:
lints
}
let (plugin, builtin): (Vec<_>, _) =
lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_plugin);
let plugin = sort_lints(sess, plugin);
let (loaded, builtin): (Vec<_>, _) =
lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_loaded);
let loaded = sort_lints(sess, loaded);
let builtin = sort_lints(sess, builtin);
let (plugin_groups, builtin_groups): (Vec<_>, _) =
let (loaded_groups, builtin_groups): (Vec<_>, _) =
lint_store.get_lint_groups().partition(|&(.., p)| p);
let plugin_groups = sort_lint_groups(plugin_groups);
let loaded_groups = sort_lint_groups(loaded_groups);
let builtin_groups = sort_lint_groups(builtin_groups);
let max_name_len =
plugin.iter().chain(&builtin).map(|&s| s.name.chars().count()).max().unwrap_or(0);
loaded.iter().chain(&builtin).map(|&s| s.name.chars().count()).max().unwrap_or(0);
let padded = |x: &str| {
let mut s = " ".repeat(max_name_len - x.chars().count());
s.push_str(x);
@ -1061,7 +1056,7 @@ Available lint options:
let max_name_len = max(
"warnings".len(),
plugin_groups
loaded_groups
.iter()
.chain(&builtin_groups)
.map(|&(s, _)| s.chars().count())
@ -1099,20 +1094,22 @@ Available lint options:
print_lint_groups(builtin_groups, true);
match (loaded_plugins, plugin.len(), plugin_groups.len()) {
match (loaded_lints, loaded.len(), loaded_groups.len()) {
(false, 0, _) | (false, _, 0) => {
safe_println!("Lint tools like Clippy can provide additional lints and lint groups.");
safe_println!("Lint tools like Clippy can load additional lints and lint groups.");
}
(false, ..) => panic!("didn't load additional lints but got them anyway!"),
(true, 0, 0) => {
safe_println!("This crate does not load any additional lints or lint groups.")
}
(false, ..) => panic!("didn't load lint plugins but got them anyway!"),
(true, 0, 0) => safe_println!("This crate does not load any lint plugins or lint groups."),
(true, l, g) => {
if l > 0 {
safe_println!("Lint checks provided by plugins loaded by this crate:\n");
print_lints(plugin);
safe_println!("Lint checks loaded by this crate:\n");
print_lints(loaded);
}
if g > 0 {
safe_println!("Lint groups provided by plugins loaded by this crate:\n");
print_lint_groups(plugin_groups, false);
safe_println!("Lint groups loaded by this crate:\n");
print_lint_groups(loaded_groups, false);
}
}
}
@ -1129,7 +1126,7 @@ pub fn describe_flag_categories(handler: &EarlyErrorHandler, matches: &Matches)
rustc_errors::FatalError.raise();
}
// Don't handle -W help here, because we might first load plugins.
// Don't handle -W help here, because we might first load additional lints.
let debug_flags = matches.opt_strs("Z");
if debug_flags.iter().any(|x| *x == "help") {
describe_debug_flags();

View file

@ -1,3 +1,5 @@
#### Note: this error code is no longer emitted by the compiler`
Plugin `..` only found in rlib format, but must be available in dylib format.
Erroneous code example:

View file

@ -1,16 +1,13 @@
A plugin/crate was declared but cannot be found.
A crate was declared but cannot be found.
Erroneous code example:
```compile_fail,E0463
#![feature(plugin)]
#![plugin(cookie_monster)] // error: can't find crate for `cookie_monster`
extern crate cake_is_a_lie; // error: can't find crate for `cake_is_a_lie`
extern crate foo; // error: can't find crate
```
You need to link your code to the relevant crate in order to be able to use it
(through Cargo or the `-L` option of rustc example). Plugins are crates as
well, and you link to them the same way.
(through Cargo or the `-L` option of rustc, for example).
## Common causes

View file

@ -1,8 +1,10 @@
#### Note: this error code is no longer emitted by the compiler.
The `plugin` attribute was malformed.
Erroneous code example:
```compile_fail,E0498
```ignore (E0498 is no longer emitted)
#![feature(plugin)]
#![plugin(foo(args))] // error: invalid argument
#![plugin(bar="test")] // error: invalid argument

View file

@ -417,24 +417,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
naked_functions, experimental!(naked)
),
// Plugins:
BuiltinAttribute {
name: sym::plugin,
only_local: false,
type_: CrateLevel,
template: template!(List: "name"),
duplicates: DuplicatesOk,
gate: Gated(
Stability::Deprecated(
"https://github.com/rust-lang/rust/pull/64675",
Some("may be removed in a future compiler version"),
),
sym::plugin,
"compiler plugins are deprecated",
cfg_fn!(plugin)
),
},
// Testing:
gated!(
test_runner, CrateLevel, template!(List: "path"), ErrorFollowing, custom_test_frameworks,

View file

@ -152,9 +152,12 @@ declare_features! (
Some("removed in favor of `#![feature(marker_trait_attr)]`")),
(removed, panic_implementation, "1.28.0", Some(44489), None,
Some("subsumed by `#[panic_handler]`")),
/// Allows using `#![plugin(myplugin)]`.
(removed, plugin, "CURRENT_RUSTC_VERSION", Some(29597), None,
Some("plugins are no longer supported")),
/// Allows using `#[plugin_registrar]` on functions.
(removed, plugin_registrar, "1.54.0", Some(29597), None,
Some("a __rustc_plugin_registrar symbol must now be defined instead")),
Some("plugins are no longer supported")),
(removed, proc_macro_expr, "1.27.0", Some(54727), None,
Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
(removed, proc_macro_gen, "1.27.0", Some(54727), None,

View file

@ -528,8 +528,6 @@ declare_features! (
(unstable, object_safe_for_dispatch, "1.40.0", Some(43561), None),
/// Allows using `#[optimize(X)]`.
(unstable, optimize_attribute, "1.34.0", Some(54882), None),
/// Allows using `#![plugin(myplugin)]`.
(unstable, plugin, "1.0.0", Some(29597), None),
/// Allows exhaustive integer pattern matching on `usize` and `isize`.
(unstable, precise_pointer_size_matching, "1.32.0", Some(56354), None),
/// Allows macro attributes on expressions, statements and non-inline modules.

View file

@ -36,7 +36,6 @@ rustc_mir_transform = { path = "../rustc_mir_transform" }
rustc_monomorphize = { path = "../rustc_monomorphize" }
rustc_parse = { path = "../rustc_parse" }
rustc_passes = { path = "../rustc_passes" }
rustc_plugin_impl = { path = "../rustc_plugin_impl" }
rustc_privacy = { path = "../rustc_privacy" }
rustc_query_impl = { path = "../rustc_query_impl" }
rustc_query_system = { path = "../rustc_query_system" }

View file

@ -354,7 +354,7 @@ pub struct Config {
pub hash_untracked_state: Option<Box<dyn FnOnce(&Session, &mut StableHasher) + Send>>,
/// This is a callback from the driver that is called when we're registering lints;
/// it is called during plugin registration when we have the LintStore in a non-shared state.
/// it is called during lint loading when we have the LintStore in a non-shared state.
///
/// Note that if you find a Some here you probably want to call that function in the new
/// function being registered.

View file

@ -23,11 +23,10 @@ use rustc_middle::util::Providers;
use rustc_mir_build as mir_build;
use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr};
use rustc_passes::{self, abi_test, hir_stats, layout_test};
use rustc_plugin_impl as plugin;
use rustc_resolve::Resolver;
use rustc_session::code_stats::VTableSizeInfo;
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
use rustc_session::cstore::{MetadataLoader, Untracked};
use rustc_session::cstore::Untracked;
use rustc_session::output::filename_for_input;
use rustc_session::search_paths::PathKind;
use rustc_session::{Limit, Session};
@ -75,25 +74,12 @@ fn count_nodes(krate: &ast::Crate) -> usize {
pub(crate) fn create_lint_store(
sess: &Session,
metadata_loader: &dyn MetadataLoader,
register_lints: Option<impl Fn(&Session, &mut LintStore)>,
pre_configured_attrs: &[ast::Attribute],
) -> LintStore {
let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints());
if let Some(register_lints) = register_lints {
register_lints(sess, &mut lint_store);
}
let registrars = sess.time("plugin_loading", || {
plugin::load::load_plugins(sess, metadata_loader, pre_configured_attrs)
});
sess.time("plugin_registration", || {
let mut registry = plugin::Registry { lint_store: &mut lint_store };
for registrar in registrars {
registrar(&mut registry);
}
});
lint_store
}

View file

@ -148,12 +148,8 @@ impl<'tcx> Queries<'tcx> {
);
let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id)?;
let lint_store = Lrc::new(passes::create_lint_store(
sess,
&*self.codegen_backend().metadata_loader(),
self.compiler.register_lints.as_deref(),
&pre_configured_attrs,
));
let lint_store =
Lrc::new(passes::create_lint_store(sess, self.compiler.register_lints.as_deref()));
let cstore = FreezeLock::new(Box::new(CStore::new(
self.codegen_backend().metadata_loader(),
stable_crate_id,

View file

@ -109,7 +109,7 @@ struct LintAlias {
struct LintGroup {
lint_ids: Vec<LintId>,
from_plugin: bool,
is_loaded: bool,
depr: Option<LintAlias>,
}
@ -160,9 +160,7 @@ impl LintStore {
// Don't display deprecated lint groups.
depr.is_none()
})
.map(|(k, LintGroup { lint_ids, from_plugin, .. })| {
(*k, lint_ids.clone(), *from_plugin)
})
.map(|(k, LintGroup { lint_ids, is_loaded, .. })| (*k, lint_ids.clone(), *is_loaded))
}
pub fn register_early_pass(
@ -221,7 +219,7 @@ impl LintStore {
.entry(edition.lint_name())
.or_insert(LintGroup {
lint_ids: vec![],
from_plugin: lint.is_plugin,
is_loaded: lint.is_loaded,
depr: None,
})
.lint_ids
@ -234,7 +232,7 @@ impl LintStore {
.entry("future_incompatible")
.or_insert(LintGroup {
lint_ids: vec![],
from_plugin: lint.is_plugin,
is_loaded: lint.is_loaded,
depr: None,
})
.lint_ids
@ -249,7 +247,7 @@ impl LintStore {
alias,
LintGroup {
lint_ids: vec![],
from_plugin: false,
is_loaded: false,
depr: Some(LintAlias { name: lint_name, silent: true }),
},
);
@ -257,21 +255,21 @@ impl LintStore {
pub fn register_group(
&mut self,
from_plugin: bool,
is_loaded: bool,
name: &'static str,
deprecated_name: Option<&'static str>,
to: Vec<LintId>,
) {
let new = self
.lint_groups
.insert(name, LintGroup { lint_ids: to, from_plugin, depr: None })
.insert(name, LintGroup { lint_ids: to, is_loaded, depr: None })
.is_none();
if let Some(deprecated) = deprecated_name {
self.lint_groups.insert(
deprecated,
LintGroup {
lint_ids: vec![],
from_plugin,
is_loaded,
depr: Some(LintAlias { name, silent: false }),
},
);

View file

@ -10,7 +10,7 @@
//! all other analyses. The `LintPass`es built into rustc are defined
//! within [rustc_session::lint::builtin],
//! which has further comments on how to add such a lint.
//! rustc can also load user-defined lint plugins via the plugin mechanism.
//! rustc can also load external lint plugins, as is done for Clippy.
//!
//! Some of rustc's lints are defined elsewhere in the compiler and work by
//! calling `add_lint()` on the overall `Session` object. This works when

View file

@ -321,7 +321,7 @@ pub struct Lint {
pub future_incompatible: Option<FutureIncompatibleInfo>,
pub is_plugin: bool,
pub is_loaded: bool,
/// `Some` if this lint is feature gated, otherwise `None`.
pub feature_gate: Option<Symbol>,
@ -399,7 +399,7 @@ impl Lint {
default_level: Level::Forbid,
desc: "",
edition_lint_opts: None,
is_plugin: false,
is_loaded: false,
report_in_external_macro: false,
future_incompatible: None,
feature_gate: None,
@ -735,7 +735,7 @@ macro_rules! declare_lint {
name: stringify!($NAME),
default_level: $crate::$Level,
desc: $desc,
is_plugin: false,
is_loaded: false,
$($v: true,)*
$(feature_gate: Some($gate),)?
$(future_incompatible: Some($crate::FutureIncompatibleInfo {
@ -777,7 +777,7 @@ macro_rules! declare_tool_lint {
edition_lint_opts: None,
report_in_external_macro: $external,
future_incompatible: None,
is_plugin: true,
is_loaded: true,
$(feature_gate: Some($gate),)?
crate_level_only: false,
..$crate::Lint::default_fields_for_macro()

View file

@ -196,9 +196,6 @@ metadata_newer_crate_version =
metadata_no_crate_with_triple =
couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info}
metadata_no_dylib_plugin =
plugin `{$crate_name}` only found in rlib format, but must be available in dylib format
metadata_no_link_mod_override =
overriding linking modifiers from command line is not supported

View file

@ -682,14 +682,6 @@ impl IntoDiagnostic<'_> for CannotFindCrate {
}
}
#[derive(Diagnostic)]
#[diag(metadata_no_dylib_plugin, code = "E0457")]
pub struct NoDylibPlugin {
#[primary_span]
pub span: Span,
pub crate_name: Symbol,
}
#[derive(Diagnostic)]
#[diag(metadata_crate_location_unknown_type)]
pub struct CrateLocationUnknownType<'a> {

View file

@ -220,7 +220,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::owned_slice::slice_owned;
use rustc_data_structures::svh::Svh;
use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_fs_util::try_canonicalize;
use rustc_session::config;
use rustc_session::cstore::{CrateSource, MetadataLoader};
@ -857,46 +857,6 @@ fn get_metadata_section<'p>(
}
}
/// Look for a plugin registrar. Returns its library path and crate disambiguator.
pub fn find_plugin_registrar(
sess: &Session,
metadata_loader: &dyn MetadataLoader,
span: Span,
name: Symbol,
) -> PathBuf {
find_plugin_registrar_impl(sess, metadata_loader, name).unwrap_or_else(|err| {
// `core` is always available if we got as far as loading plugins.
err.report(sess, span, false);
FatalError.raise()
})
}
fn find_plugin_registrar_impl<'a>(
sess: &'a Session,
metadata_loader: &dyn MetadataLoader,
name: Symbol,
) -> Result<PathBuf, CrateError> {
info!("find plugin registrar `{}`", name);
let mut locator = CrateLocator::new(
sess,
metadata_loader,
name,
false, // is_rlib
None, // hash
None, // extra_filename
true, // is_host
PathKind::Crate,
);
match locator.maybe_load_library_crate()? {
Some(library) => match library.source.dylib {
Some(dylib) => Ok(dylib.0),
None => Err(CrateError::NonDylibPlugin(name)),
},
None => Err(locator.into_error(None)),
}
}
/// A diagnostic function for dumping crate metadata to an output stream.
pub fn list_file_metadata(
target: &Target,
@ -964,7 +924,6 @@ pub(crate) enum CrateError {
DlOpen(String),
DlSym(String),
LocatorCombined(Box<CombinedLocatorError>),
NonDylibPlugin(Symbol),
NotFound(Symbol),
}
@ -1134,9 +1093,6 @@ impl CrateError {
});
}
}
CrateError::NonDylibPlugin(crate_name) => {
sess.emit_err(errors::NoDylibPlugin { span, crate_name });
}
CrateError::NotFound(crate_name) => {
sess.emit_err(errors::CannotFindCrate {
span,

View file

@ -17,8 +17,7 @@ use crate::ty::TyCtxt;
/// How a lint level was set.
#[derive(Clone, Copy, PartialEq, Eq, HashStable, Debug)]
pub enum LintLevelSource {
/// Lint is at the default level as declared
/// in rustc or a plugin.
/// Lint is at the default level as declared in rustc.
Default,
/// Lint level was set by an attribute.

View file

@ -589,9 +589,6 @@ passes_pass_by_value =
`pass_by_value` attribute should be applied to a struct, enum or type alias
.label = is not a struct, enum or type alias
passes_plugin_registrar =
`#[plugin_registrar]` only has an effect on functions
passes_proc_macro_bad_sig = {$kind} has incorrect signature
passes_repr_conflicting =

View file

@ -211,7 +211,6 @@ impl CheckAttrVisitor<'_> {
sym::deprecated => self.check_deprecated(hir_id, attr, span, target),
sym::macro_use | sym::macro_escape => self.check_macro_use(hir_id, attr, target),
sym::path => self.check_generic_attr(hir_id, attr, target, Target::Mod),
sym::plugin_registrar => self.check_plugin_registrar(hir_id, attr, target),
sym::macro_export => self.check_macro_export(hir_id, attr, target),
sym::ignore | sym::should_panic => {
self.check_generic_attr(hir_id, attr, target, Target::Fn)
@ -2237,17 +2236,6 @@ impl CheckAttrVisitor<'_> {
}
}
fn check_plugin_registrar(&self, hir_id: HirId, attr: &Attribute, target: Target) {
if target != Target::Fn {
self.tcx.emit_spanned_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
errors::PluginRegistrar,
);
}
}
fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute) {
// Warn on useless empty attributes.
let note = if matches!(

View file

@ -717,10 +717,6 @@ pub enum MacroExport {
TooManyItems,
}
#[derive(LintDiagnostic)]
#[diag(passes_plugin_registrar)]
pub struct PluginRegistrar;
#[derive(Subdiagnostic)]
pub enum UnusedNote {
#[note(passes_unused_empty_lints_note)]

View file

@ -1,18 +0,0 @@
[package]
name = "rustc_plugin_impl"
version = "0.0.0"
build = false
edition = "2021"
[dependencies]
# tidy-alphabetical-start
libloading = "0.7.1"
rustc_ast = { path = "../rustc_ast" }
rustc_errors = { path = "../rustc_errors" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_lint = { path = "../rustc_lint" }
rustc_macros = { path = "../rustc_macros" }
rustc_metadata = { path = "../rustc_metadata" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
# tidy-alphabetical-end

View file

@ -1,4 +0,0 @@
plugin_impl_load_plugin_error = {$msg}
plugin_impl_malformed_plugin_attribute = malformed `plugin` attribute
.label = malformed attribute

View file

@ -1,20 +0,0 @@
//! Errors emitted by plugin_impl
use rustc_macros::Diagnostic;
use rustc_span::Span;
#[derive(Diagnostic)]
#[diag(plugin_impl_load_plugin_error)]
pub struct LoadPluginError {
#[primary_span]
pub span: Span,
pub msg: String,
}
#[derive(Diagnostic)]
#[diag(plugin_impl_malformed_plugin_attribute, code = "E0498")]
pub struct MalformedPluginAttribute {
#[primary_span]
#[label]
pub span: Span,
}

View file

@ -1,33 +0,0 @@
//! Infrastructure for compiler plugins.
//!
//! Plugins are a deprecated way to extend the behavior of `rustc` in various ways.
//!
//! See the [`plugin`
//! feature](https://doc.rust-lang.org/nightly/unstable-book/language-features/plugin.html)
//! of the Unstable Book for some examples.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![cfg_attr(not(bootstrap), doc(rust_logo))]
#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
#![cfg_attr(not(bootstrap), allow(internal_features))]
#![recursion_limit = "256"]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_fluent_macro::fluent_messages;
use rustc_lint::LintStore;
mod errors;
pub mod load;
fluent_messages! { "../messages.ftl" }
/// Structure used to register plugins.
///
/// A plugin registrar function takes an `&mut Registry` and should call
/// methods to register its plugins.
pub struct Registry<'a> {
/// The `LintStore` allows plugins to register new lints.
pub lint_store: &'a mut LintStore,
}

View file

@ -1,78 +0,0 @@
//! Used by `rustc` when loading a plugin.
use crate::errors::{LoadPluginError, MalformedPluginAttribute};
use crate::Registry;
use libloading::Library;
use rustc_ast::Attribute;
use rustc_metadata::locator;
use rustc_session::cstore::MetadataLoader;
use rustc_session::Session;
use rustc_span::symbol::{sym, Ident};
use std::env;
use std::mem;
use std::path::PathBuf;
/// Pointer to a registrar function.
type PluginRegistrarFn = fn(&mut Registry<'_>);
/// Read plugin metadata and dynamically load registrar functions.
pub fn load_plugins(
sess: &Session,
metadata_loader: &dyn MetadataLoader,
attrs: &[Attribute],
) -> Vec<PluginRegistrarFn> {
let mut plugins = Vec::new();
for attr in attrs {
if !attr.has_name(sym::plugin) {
continue;
}
for plugin in attr.meta_item_list().unwrap_or_default() {
match plugin.ident() {
Some(ident) if plugin.is_word() => {
load_plugin(&mut plugins, sess, metadata_loader, ident)
}
_ => {
sess.emit_err(MalformedPluginAttribute { span: plugin.span() });
}
}
}
}
plugins
}
fn load_plugin(
plugins: &mut Vec<PluginRegistrarFn>,
sess: &Session,
metadata_loader: &dyn MetadataLoader,
ident: Ident,
) {
let lib = locator::find_plugin_registrar(sess, metadata_loader, ident.span, ident.name);
let fun = dylink_registrar(lib).unwrap_or_else(|err| {
// This is fatal: there are almost certainly macros we need inside this crate, so
// continuing would spew "macro undefined" errors.
sess.emit_fatal(LoadPluginError { span: ident.span, msg: err.to_string() });
});
plugins.push(fun);
}
/// Dynamically link a registrar function into the compiler process.
fn dylink_registrar(lib_path: PathBuf) -> Result<PluginRegistrarFn, libloading::Error> {
// Make sure the path contains a / or the linker will search for it.
let lib_path = env::current_dir().unwrap().join(&lib_path);
let lib = unsafe { Library::new(&lib_path) }?;
let registrar_sym = unsafe { lib.get::<PluginRegistrarFn>(b"__rustc_plugin_registrar") }?;
// Intentionally leak the dynamic library. We can't ever unload it
// since the library can make things that will live arbitrarily long
// (e.g., an Rc cycle or a thread).
let registrar_sym = unsafe { registrar_sym.into_raw() };
mem::forget(lib);
Ok(*registrar_sym)
}