Skip to content

Commit

Permalink
Lower const params with a bad id
Browse files Browse the repository at this point in the history
  • Loading branch information
HKalbasi committed May 31, 2023
1 parent 76d8650 commit e238389
Show file tree
Hide file tree
Showing 38 changed files with 450 additions and 200 deletions.
6 changes: 3 additions & 3 deletions crates/base-db/src/fixture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ impl ChangeFixture {
None,
default_cfg,
Default::default(),
Env::default(),
Env::new_for_test_fixture(),
false,
CrateOrigin::Local { repo: None, name: None },
default_target_data_layout
Expand Down Expand Up @@ -259,7 +259,7 @@ impl ChangeFixture {
None,
Default::default(),
Default::default(),
Env::default(),
Env::new_for_test_fixture(),
false,
CrateOrigin::Lang(LangCrateOrigin::Core),
target_layout.clone(),
Expand Down Expand Up @@ -298,7 +298,7 @@ impl ChangeFixture {
None,
Default::default(),
Default::default(),
Env::default(),
Env::new_for_test_fixture(),
true,
CrateOrigin::Local { repo: None, name: None },
target_layout,
Expand Down
17 changes: 17 additions & 0 deletions crates/base-db/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ pub enum CrateOrigin {
Lang(LangCrateOrigin),
}

impl CrateOrigin {
pub fn is_local(&self) -> bool {
matches!(self, CrateOrigin::Local { .. })
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LangCrateOrigin {
Alloc,
Expand Down Expand Up @@ -333,6 +339,17 @@ pub struct Env {
entries: FxHashMap<String, String>,
}

impl Env {
pub fn new_for_test_fixture() -> Self {
Env {
entries: FxHashMap::from_iter([(
String::from("__ra_is_test_fixture"),
String::from("__ra_is_test_fixture"),
)]),
}
}
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Dependency {
pub crate_id: CrateId,
Expand Down
20 changes: 9 additions & 11 deletions crates/hir-def/src/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ impl Body {
let _p = profile::span("body_with_source_map_query");
let mut params = None;

let (file_id, module, body, is_async_fn) = {
let (file_id, body, is_async_fn) = {
match def {
DefWithBodyId::FunctionId(f) => {
let data = db.function_data(f);
Expand All @@ -138,31 +138,29 @@ impl Body {
}),
)
});
(
src.file_id,
f.module(db),
src.value.body().map(ast::Expr::from),
data.has_async_kw(),
)
(src.file_id, src.value.body().map(ast::Expr::from), data.has_async_kw())
}
DefWithBodyId::ConstId(c) => {
let c = c.lookup(db);
let src = c.source(db);
(src.file_id, c.module(db), src.value.body(), false)
(src.file_id, src.value.body(), false)
}
DefWithBodyId::StaticId(s) => {
let s = s.lookup(db);
let src = s.source(db);
(src.file_id, s.module(db), src.value.body(), false)
(src.file_id, src.value.body(), false)
}
DefWithBodyId::VariantId(v) => {
let e = v.parent.lookup(db);
let src = v.parent.child_source(db);
let variant = &src.value[v.local_id];
(src.file_id, e.container, variant.expr(), false)
(src.file_id, variant.expr(), false)
}
DefWithBodyId::InTypeConstId(c) => {
(c.lookup(db).0.file_id, Some(c.source(db)), false)
}
}
};
let module = def.module(db);
let expander = Expander::new(db, file_id, module);
let (mut body, source_map) =
Body::new(db, def, expander, params, body, module.krate, is_async_fn);
Expand Down
1 change: 1 addition & 0 deletions crates/hir-def/src/body/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBo
};
format!("const {name} = ")
}
DefWithBodyId::InTypeConstId(_) => format!("In type const = "),
DefWithBodyId::VariantId(it) => {
let src = it.parent.child_source(db);
let variant = &src.value[it.local_id];
Expand Down
12 changes: 9 additions & 3 deletions crates/hir-def/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ use crate::{
visibility::{self, Visibility},
AnonymousConstId, AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId,
EnumLoc, ExternBlockId, ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc,
LocalEnumVariantId, LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, MacroRulesLoc,
ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId,
TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId,
InTypeConstId, LocalEnumVariantId, LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId,
MacroRulesLoc, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc,
TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, TypeOwnerId,
UnionId, UnionLoc, VariantId,
};

#[salsa::query_group(InternDatabaseStorage)]
Expand Down Expand Up @@ -63,6 +64,11 @@ pub trait InternDatabase: SourceDatabase {
fn intern_macro_rules(&self, loc: MacroRulesLoc) -> MacroRulesId;
#[salsa::interned]
fn intern_anonymous_const(&self, id: (DefWithBodyId, ExprId)) -> AnonymousConstId;
#[salsa::interned]
fn intern_in_type_const(
&self,
id: (hir_expand::InFile<hir_expand::ast_id_map::FileAstId<ast::Expr>>, TypeOwnerId),
) -> InTypeConstId;
}

#[salsa::query_group(DefDatabaseStorage)]
Expand Down
2 changes: 1 addition & 1 deletion crates/hir-def/src/expander.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ impl Expander {
}

pub(crate) fn parse_path(&mut self, db: &dyn DefDatabase, path: ast::Path) -> Option<Path> {
let ctx = LowerCtx::with_hygiene(db, &self.cfg_expander.hygiene);
let ctx = LowerCtx::new(db, &self.cfg_expander.hygiene, self.current_file_id);
Path::from_src(path, &ctx)
}

Expand Down
110 changes: 62 additions & 48 deletions crates/hir-def/src/hir/type_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ use core::fmt;
use std::fmt::Write;

use hir_expand::{
ast_id_map::FileAstId,
db::ExpandDatabase,
name::{AsName, Name},
AstId,
AstId, InFile,
};
use intern::Interned;
use syntax::ast::{self, HasName};
Expand Down Expand Up @@ -118,7 +119,7 @@ pub enum TypeRef {
Reference(Box<TypeRef>, Option<LifetimeRef>, Mutability),
// FIXME: for full const generics, the latter element (length) here is going to have to be an
// expression that is further lowered later in hir_ty.
Array(Box<TypeRef>, ConstRefOrPath),
Array(Box<TypeRef>, ConstRef),
Slice(Box<TypeRef>),
/// A fn pointer. Last element of the vector is the return type.
Fn(Vec<(Option<Name>, TypeRef)>, bool /*varargs*/, bool /*is_unsafe*/),
Expand Down Expand Up @@ -190,7 +191,7 @@ impl TypeRef {
// `hir_def::body::lower` to lower this into an `Expr` and then evaluate it at the
// `hir_ty` level, which would allow knowing the type of:
// let v: [u8; 2 + 2] = [0u8; 4];
let len = ConstRefOrPath::from_expr_opt(inner.expr());
let len = ConstRef::from_expr_opt(ctx, inner.expr());
TypeRef::Array(Box::new(TypeRef::from_ast_opt(ctx, inner.ty())), len)
}
ast::Type::SliceType(inner) => {
Expand Down Expand Up @@ -380,73 +381,84 @@ impl TypeBound {
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ConstRefOrPath {
Scalar(ConstRef),
pub enum ConstRef {
Scalar(ConcreteConstRef),
Path(Name),
Complex(InFile<FileAstId<ast::Expr>>),
}

impl ConstRefOrPath {
pub(crate) fn from_expr_opt(expr: Option<ast::Expr>) -> Self {
impl ConstRef {
pub(crate) fn from_expr_opt(lower_ctx: &LowerCtx<'_>, expr: Option<ast::Expr>) -> Self {
match expr {
Some(x) => Self::from_expr(x),
None => Self::Scalar(ConstRef::Unknown),
Some(x) => {
let ast_id = lower_ctx.ast_id(&x);
Self::from_expr(x, ast_id)
}
None => Self::Scalar(ConcreteConstRef::Unknown),
}
}

pub fn display<'a>(&'a self, db: &'a dyn ExpandDatabase) -> impl fmt::Display + 'a {
struct Display<'a>(&'a dyn ExpandDatabase, &'a ConstRefOrPath);
struct Display<'a>(&'a dyn ExpandDatabase, &'a ConstRef);
impl fmt::Display for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.1 {
ConstRefOrPath::Scalar(s) => s.fmt(f),
ConstRefOrPath::Path(n) => n.display(self.0).fmt(f),
ConstRef::Scalar(s) => s.fmt(f),
ConstRef::Path(n) => n.display(self.0).fmt(f),
ConstRef::Complex(_) => f.write_str("{const}"),
}
}
}
Display(db, self)
}

// FIXME: as per the comments on `TypeRef::Array`, this evaluation should not happen at this
// parse stage.
fn from_expr(expr: ast::Expr) -> Self {
// We special case literals and single identifiers, to speed up things.
fn from_expr(expr: ast::Expr, ast_id: Option<InFile<FileAstId<ast::Expr>>>) -> Self {
fn is_path_ident(p: &ast::PathExpr) -> bool {
let Some(path) = p.path() else {
return false;
};
if path.coloncolon_token().is_some() {
return false;
}
if let Some(s) = path.segment() {
if s.coloncolon_token().is_some() || s.generic_arg_list().is_some() {
return false;
}
}
true
}
match expr {
ast::Expr::PathExpr(p) => {
ast::Expr::PathExpr(p) if is_path_ident(&p) => {
match p.path().and_then(|x| x.segment()).and_then(|x| x.name_ref()) {
Some(x) => Self::Path(x.as_name()),
None => Self::Scalar(ConstRef::Unknown),
None => Self::Scalar(ConcreteConstRef::Unknown),
}
}
ast::Expr::PrefixExpr(prefix_expr) => match prefix_expr.op_kind() {
Some(ast::UnaryOp::Neg) => {
let unsigned = Self::from_expr_opt(prefix_expr.expr());
// Add sign
match unsigned {
Self::Scalar(ConstRef::UInt(num)) => {
Self::Scalar(ConstRef::Int(-(num as i128)))
}
other => other,
}
}
_ => Self::from_expr_opt(prefix_expr.expr()),
},
ast::Expr::Literal(literal) => Self::Scalar(match literal.kind() {
ast::LiteralKind::IntNumber(num) => {
num.value().map(ConstRef::UInt).unwrap_or(ConstRef::Unknown)
num.value().map(ConcreteConstRef::UInt).unwrap_or(ConcreteConstRef::Unknown)
}
ast::LiteralKind::Char(c) => {
c.value().map(ConstRef::Char).unwrap_or(ConstRef::Unknown)
c.value().map(ConcreteConstRef::Char).unwrap_or(ConcreteConstRef::Unknown)
}
ast::LiteralKind::Bool(f) => ConstRef::Bool(f),
_ => ConstRef::Unknown,
ast::LiteralKind::Bool(f) => ConcreteConstRef::Bool(f),
_ => ConcreteConstRef::Unknown,
}),
_ => Self::Scalar(ConstRef::Unknown),
_ => {
if let Some(ast_id) = ast_id {
Self::Complex(ast_id)
} else {
Self::Scalar(ConcreteConstRef::Unknown)
}
}
}
}
}

/// A concrete constant value
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ConstRef {
pub enum ConcreteConstRef {
Int(i128),
UInt(u128),
Bool(bool),
Expand All @@ -460,18 +472,20 @@ pub enum ConstRef {
Unknown,
}

impl ConstRef {
impl ConcreteConstRef {
pub fn builtin_type(&self) -> BuiltinType {
match self {
ConstRef::UInt(_) | ConstRef::Unknown => BuiltinType::Uint(BuiltinUint::U128),
ConstRef::Int(_) => BuiltinType::Int(BuiltinInt::I128),
ConstRef::Char(_) => BuiltinType::Char,
ConstRef::Bool(_) => BuiltinType::Bool,
ConcreteConstRef::UInt(_) | ConcreteConstRef::Unknown => {
BuiltinType::Uint(BuiltinUint::U128)
}
ConcreteConstRef::Int(_) => BuiltinType::Int(BuiltinInt::I128),
ConcreteConstRef::Char(_) => BuiltinType::Char,
ConcreteConstRef::Bool(_) => BuiltinType::Bool,
}
}
}

impl From<Literal> for ConstRef {
impl From<Literal> for ConcreteConstRef {
fn from(literal: Literal) -> Self {
match literal {
Literal::Char(c) => Self::Char(c),
Expand All @@ -483,14 +497,14 @@ impl From<Literal> for ConstRef {
}
}

impl std::fmt::Display for ConstRef {
impl std::fmt::Display for ConcreteConstRef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
ConstRef::Int(num) => num.fmt(f),
ConstRef::UInt(num) => num.fmt(f),
ConstRef::Bool(flag) => flag.fmt(f),
ConstRef::Char(c) => write!(f, "'{c}'"),
ConstRef::Unknown => f.write_char('_'),
ConcreteConstRef::Int(num) => num.fmt(f),
ConcreteConstRef::UInt(num) => num.fmt(f),
ConcreteConstRef::Bool(flag) => flag.fmt(f),
ConcreteConstRef::Char(c) => write!(f, "'{c}'"),
ConcreteConstRef::Unknown => f.write_char('_'),
}
}
}
Loading

0 comments on commit e238389

Please sign in to comment.