internal: Remove Edition::CURRENT_FIXME

This commit is contained in:
Lukas Wirth 2026-01-18 13:35:42 +01:00
parent 7cb789d982
commit 85b60ac340
10 changed files with 70 additions and 57 deletions

View File

@ -192,8 +192,6 @@ unused_lifetimes = "warn"
unreachable_pub = "warn"
[workspace.lints.clippy]
# FIXME Remove the tidy test once the lint table is stable
## lint groups
complexity = { level = "warn", priority = -1 }
correctness = { level = "deny", priority = -1 }

View File

@ -724,7 +724,7 @@ impl<'a> Parser<'a> {
// {foo(bar {}}
// - ^
// | |
// | help: `)` may belong here (FIXME: #58270)
// | help: `)` may belong here
// |
// unclosed delimiter
if let Some(sp) = unmatched.unclosed_span {
@ -3217,7 +3217,6 @@ impl<'a> Parser<'a> {
}
_ => {
// FIXME Could factor this out into non_fatal_unexpected or something.
let actual = self.this_token_to_string();
self.span_err(self.span, &format!("unexpected token: `{}`", actual));
}
@ -5250,7 +5249,6 @@ impl<'a> Parser<'a> {
}
}
} else {
// FIXME: Bad copy of attrs
let old_directory_ownership =
mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
let item = self.parse_item_(attrs.clone(), false, true)?;
@ -5953,23 +5951,14 @@ impl<'a> Parser<'a> {
});
assoc_ty_bindings.push(span);
} else if self.check_const_arg() {
// FIXME(const_generics): to distinguish between idents for types and consts,
// we should introduce a GenericArg::Ident in the AST and distinguish when
// lowering to the HIR. For now, idents for const args are not permitted.
// Parse const argument.
let expr = if let token::OpenDelim(token::Brace) = self.token {
self.parse_block_expr(None, self.span, BlockCheckMode::Default, ThinVec::new())?
} else if self.token.is_ident() {
// FIXME(const_generics): to distinguish between idents for types and consts,
// we should introduce a GenericArg::Ident in the AST and distinguish when
// lowering to the HIR. For now, idents for const args are not permitted.
return Err(
self.fatal("identifiers may currently not be used for const generics")
);
} else {
// FIXME(const_generics): this currently conflicts with emplacement syntax
// with negative integer literals.
self.parse_literal_maybe_minus()?
};
let value = AnonConst {
@ -5991,9 +5980,6 @@ impl<'a> Parser<'a> {
}
}
// FIXME: we would like to report this in ast_validation instead, but we currently do not
// preserve ordering of generic parameters with respect to associated type binding, so we
// lose that information after parsing.
if misplaced_assoc_ty_bindings.len() > 0 {
let mut err = self.struct_span_err(
args_lo.to(self.prev_span),
@ -6079,8 +6065,6 @@ impl<'a> Parser<'a> {
bounds,
}
));
// FIXME: Decide what should be used here, `=` or `==`.
// FIXME: We are just dropping the binders in lifetime_defs on the floor here.
} else if self.eat(&token::Eq) || self.eat(&token::EqEq) {
let rhs_ty = self.parse_ty()?;
where_clause.predicates.push(ast::WherePredicate::EqPredicate(

View File

@ -16,8 +16,6 @@ impl Edition {
pub const DEFAULT: Edition = Edition::Edition2015;
pub const LATEST: Edition = Edition::Edition2024;
pub const CURRENT: Edition = Edition::Edition2024;
/// The current latest stable edition, note this is usually not the right choice in code.
pub const CURRENT_FIXME: Edition = Edition::Edition2024;
pub fn from_u32(u32: u32) -> Edition {
match u32 {

View File

@ -18,7 +18,6 @@ use hir_ty::{
use itertools::Itertools;
use rustc_hash::FxHashSet;
use rustc_type_ir::inherent::Ty as _;
use span::Edition;
use crate::{
Adt, AssocItem, GenericDef, GenericParam, HasAttrs, HasVisibility, Impl, ModuleDef, ScopeDef,
@ -367,7 +366,11 @@ pub(super) fn free_function<'a, 'lt, 'db, DB: HirDatabase>(
let ret_ty = it.ret_type_with_args(db, generics.iter().cloned());
// Filter out private and unsafe functions
if !it.is_visible_from(db, module)
|| it.is_unsafe_to_call(db, None, Edition::CURRENT_FIXME)
|| it.is_unsafe_to_call(
db,
None,
crate::Crate::from(ctx.scope.resolver().krate()).edition(db),
)
|| it.is_unstable(db)
|| ctx.config.enable_borrowcheck && ret_ty.contains_reference(db)
|| ret_ty.is_raw_ptr()
@ -473,7 +476,11 @@ pub(super) fn impl_method<'a, 'lt, 'db, DB: HirDatabase>(
// Filter out private and unsafe functions
if !it.is_visible_from(db, module)
|| it.is_unsafe_to_call(db, None, Edition::CURRENT_FIXME)
|| it.is_unsafe_to_call(
db,
None,
crate::Crate::from(ctx.scope.resolver().krate()).edition(db),
)
|| it.is_unstable(db)
{
return None;
@ -667,7 +674,11 @@ pub(super) fn impl_static_method<'a, 'lt, 'db, DB: HirDatabase>(
// Filter out private and unsafe functions
if !it.is_visible_from(db, module)
|| it.is_unsafe_to_call(db, None, Edition::CURRENT_FIXME)
|| it.is_unsafe_to_call(
db,
None,
crate::Crate::from(ctx.scope.resolver().krate()).edition(db),
)
|| it.is_unstable(db)
{
return None;

View File

@ -155,6 +155,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
&scope,
mod_path_to_ast(&import_path, edition),
&ctx.config.insert_use,
edition,
);
},
);

View File

@ -146,9 +146,14 @@ pub fn insert_use(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) {
insert_use_with_alias_option(scope, path, cfg, None);
}
pub fn insert_use_as_alias(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) {
pub fn insert_use_as_alias(
scope: &ImportScope,
path: ast::Path,
cfg: &InsertUseConfig,
edition: span::Edition,
) {
let text: &str = "use foo as _";
let parse = syntax::SourceFile::parse(text, span::Edition::CURRENT_FIXME);
let parse = syntax::SourceFile::parse(text, edition);
let node = parse
.tree()
.syntax()

View File

@ -206,17 +206,18 @@ impl NameGenerator {
expr: &ast::Expr,
sema: &Semantics<'_, RootDatabase>,
) -> Option<SmolStr> {
let edition = sema.scope(expr.syntax())?.krate().edition(sema.db);
// `from_param` does not benefit from stripping it need the largest
// context possible so we check firstmost
if let Some(name) = from_param(expr, sema) {
if let Some(name) = from_param(expr, sema, edition) {
return Some(self.suggest_name(&name));
}
let mut next_expr = Some(expr.clone());
while let Some(expr) = next_expr {
let name = from_call(&expr)
.or_else(|| from_type(&expr, sema))
.or_else(|| from_field_name(&expr));
let name = from_call(&expr, edition)
.or_else(|| from_type(&expr, sema, edition))
.or_else(|| from_field_name(&expr, edition));
if let Some(name) = name {
return Some(self.suggest_name(&name));
}
@ -270,7 +271,7 @@ impl NameGenerator {
}
}
fn normalize(name: &str) -> Option<SmolStr> {
fn normalize(name: &str, edition: syntax::Edition) -> Option<SmolStr> {
let name = to_lower_snake_case(name).to_smolstr();
if USELESS_NAMES.contains(&name.as_str()) {
@ -281,16 +282,16 @@ fn normalize(name: &str) -> Option<SmolStr> {
return None;
}
if !is_valid_name(&name) {
if !is_valid_name(&name, edition) {
return None;
}
Some(name)
}
fn is_valid_name(name: &str) -> bool {
fn is_valid_name(name: &str, edition: syntax::Edition) -> bool {
matches!(
super::LexedStr::single_token(syntax::Edition::CURRENT_FIXME, name),
super::LexedStr::single_token(edition, name),
Some((syntax::SyntaxKind::IDENT, _error))
)
}
@ -304,11 +305,11 @@ fn is_useless_method(method: &ast::MethodCallExpr) -> bool {
}
}
fn from_call(expr: &ast::Expr) -> Option<SmolStr> {
from_func_call(expr).or_else(|| from_method_call(expr))
fn from_call(expr: &ast::Expr, edition: syntax::Edition) -> Option<SmolStr> {
from_func_call(expr, edition).or_else(|| from_method_call(expr, edition))
}
fn from_func_call(expr: &ast::Expr) -> Option<SmolStr> {
fn from_func_call(expr: &ast::Expr, edition: syntax::Edition) -> Option<SmolStr> {
let call = match expr {
ast::Expr::CallExpr(call) => call,
_ => return None,
@ -318,10 +319,10 @@ fn from_func_call(expr: &ast::Expr) -> Option<SmolStr> {
_ => return None,
};
let ident = func.path()?.segment()?.name_ref()?.ident_token()?;
normalize(ident.text())
normalize(ident.text(), edition)
}
fn from_method_call(expr: &ast::Expr) -> Option<SmolStr> {
fn from_method_call(expr: &ast::Expr, edition: syntax::Edition) -> Option<SmolStr> {
let method = match expr {
ast::Expr::MethodCallExpr(call) => call,
_ => return None,
@ -340,10 +341,14 @@ fn from_method_call(expr: &ast::Expr) -> Option<SmolStr> {
}
}
normalize(name)
normalize(name, edition)
}
fn from_param(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<SmolStr> {
fn from_param(
expr: &ast::Expr,
sema: &Semantics<'_, RootDatabase>,
edition: Edition,
) -> Option<SmolStr> {
let arg_list = expr.syntax().parent().and_then(ast::ArgList::cast)?;
let args_parent = arg_list.syntax().parent()?;
let func = match_ast! {
@ -362,7 +367,7 @@ fn from_param(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<Sm
let param = func.params().into_iter().nth(idx)?;
let pat = sema.source(param)?.value.right()?.pat()?;
let name = var_name_from_pat(&pat)?;
normalize(&name.to_smolstr())
normalize(&name.to_smolstr(), edition)
}
fn var_name_from_pat(pat: &ast::Pat) -> Option<ast::Name> {
@ -374,10 +379,13 @@ fn var_name_from_pat(pat: &ast::Pat) -> Option<ast::Name> {
}
}
fn from_type(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<SmolStr> {
fn from_type(
expr: &ast::Expr,
sema: &Semantics<'_, RootDatabase>,
edition: Edition,
) -> Option<SmolStr> {
let ty = sema.type_of_expr(expr)?.adjusted();
let ty = ty.remove_ref().unwrap_or(ty);
let edition = sema.scope(expr.syntax())?.krate().edition(sema.db);
name_of_type(&ty, sema.db, edition)
}
@ -417,7 +425,7 @@ fn name_of_type<'db>(
} else {
return None;
};
normalize(&name)
normalize(&name, edition)
}
fn sequence_name<'db>(
@ -450,13 +458,13 @@ fn trait_name(trait_: &hir::Trait, db: &RootDatabase, edition: Edition) -> Optio
Some(name)
}
fn from_field_name(expr: &ast::Expr) -> Option<SmolStr> {
fn from_field_name(expr: &ast::Expr, edition: syntax::Edition) -> Option<SmolStr> {
let field = match expr {
ast::Expr::FieldExpr(field) => field,
_ => return None,
};
let ident = field.name_ref()?.ident_token()?;
normalize(ident.text())
normalize(ident.text(), edition)
}
#[cfg(test)]

View File

@ -17,7 +17,10 @@ mod on_enter;
use either::Either;
use hir::EditionedFileId;
use ide_db::{FilePosition, RootDatabase, base_db::RootQueryDb};
use ide_db::{
FilePosition, RootDatabase,
base_db::{RootQueryDb, SourceDatabase},
};
use span::Edition;
use std::iter;
@ -70,11 +73,12 @@ pub(crate) fn on_char_typed(
if !TRIGGER_CHARS.contains(&char_typed) {
return None;
}
// FIXME: We need to figure out the edition of the file here, but that means hitting the
// database for more than just parsing the file which is bad.
let edition = db
.source_root_crates(db.file_source_root(position.file_id).source_root_id(db))
.first()
.map_or(Edition::CURRENT, |crates| crates.data(db).edition);
// FIXME: We are hitting the database here, if we are unlucky this call might block momentarily
// causing the editor to feel sluggish!
let edition = Edition::CURRENT_FIXME;
// causing the editor to feel sluggish! We need to make this bail if it would block too long?
let editioned_file_id_wrapper = EditionedFileId::from_span_guess_origin(
db,
span::EditionedFileId::new(position.file_id, edition),
@ -457,8 +461,8 @@ mod tests {
let (offset, mut before) = extract_offset(before);
let edit = TextEdit::insert(offset, char_typed.to_string());
edit.apply(&mut before);
let parse = SourceFile::parse(&before, span::Edition::CURRENT_FIXME);
on_char_typed_(&parse, offset, char_typed, span::Edition::CURRENT_FIXME).map(|it| {
let parse = SourceFile::parse(&before, span::Edition::CURRENT);
on_char_typed_(&parse, offset, char_typed, span::Edition::CURRENT).map(|it| {
it.apply(&mut before);
before.to_string()
})

View File

@ -275,7 +275,10 @@ impl Sysroot {
}
tracing::debug!("Stitching sysroot library: {src_root}");
let mut stitched = stitched::Stitched { crates: Default::default() };
let mut stitched = stitched::Stitched {
crates: Default::default(),
edition: span::Edition::Edition2024,
};
for path in stitched::SYSROOT_CRATES.trim().lines() {
let name = path.split('/').next_back().unwrap();
@ -511,6 +514,7 @@ pub(crate) mod stitched {
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Stitched {
pub(super) crates: Arena<RustLibSrcCrateData>,
pub(crate) edition: span::Edition,
}
impl ops::Index<RustLibSrcCrate> for Stitched {

View File

@ -1831,7 +1831,7 @@ fn sysroot_to_crate_graph(
let display_name = CrateDisplayName::from_canonical_name(&stitched[krate].name);
let crate_id = crate_graph.add_crate_root(
file_id,
Edition::CURRENT_FIXME,
stitched.edition,
Some(display_name),
None,
cfg_options.clone(),