mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-25 19:35:06 +00:00
Merge from rustc
This commit is contained in:
commit
77d9741320
60 changed files with 714 additions and 402 deletions
15
.github/workflows/ci.yaml
vendored
15
.github/workflows/ci.yaml
vendored
|
@ -161,10 +161,21 @@ jobs:
|
||||||
# if: runner.os == 'Linux'
|
# if: runner.os == 'Linux'
|
||||||
# working-directory: ./editors/code
|
# working-directory: ./editors/code
|
||||||
|
|
||||||
|
# If this steps fails, your code's type integrity might be wrong at some places at TypeScript level.
|
||||||
|
- run: npm run typecheck
|
||||||
|
working-directory: ./editors/code
|
||||||
|
if: needs.changes.outputs.typescript == 'true'
|
||||||
|
|
||||||
|
# You may fix the code automatically by running `npm run lint:fix` if this steps fails.
|
||||||
- run: npm run lint
|
- run: npm run lint
|
||||||
working-directory: ./editors/code
|
working-directory: ./editors/code
|
||||||
if: needs.changes.outputs.typescript == 'true'
|
if: needs.changes.outputs.typescript == 'true'
|
||||||
|
|
||||||
|
# To fix this steps, please run `npm run format`.
|
||||||
|
- run: npm run format:check
|
||||||
|
working-directory: ./editors/code
|
||||||
|
if: needs.changes.outputs.typescript == 'true'
|
||||||
|
|
||||||
- name: Run VS Code tests (Linux)
|
- name: Run VS Code tests (Linux)
|
||||||
if: matrix.os == 'ubuntu-latest' && needs.changes.outputs.typescript == 'true'
|
if: matrix.os == 'ubuntu-latest' && needs.changes.outputs.typescript == 'true'
|
||||||
env:
|
env:
|
||||||
|
@ -179,10 +190,6 @@ jobs:
|
||||||
run: npm test
|
run: npm test
|
||||||
working-directory: ./editors/code
|
working-directory: ./editors/code
|
||||||
|
|
||||||
- run: npm run pretest
|
|
||||||
working-directory: ./editors/code
|
|
||||||
if: needs.changes.outputs.typescript == 'true'
|
|
||||||
|
|
||||||
- run: npm run package --scripts-prepend-node-path
|
- run: npm run package --scripts-prepend-node-path
|
||||||
working-directory: ./editors/code
|
working-directory: ./editors/code
|
||||||
if: needs.changes.outputs.typescript == 'true'
|
if: needs.changes.outputs.typescript == 'true'
|
||||||
|
|
|
@ -634,7 +634,7 @@ impl Printer<'_> {
|
||||||
match literal {
|
match literal {
|
||||||
Literal::String(it) => w!(self, "{:?}", it),
|
Literal::String(it) => w!(self, "{:?}", it),
|
||||||
Literal::ByteString(it) => w!(self, "\"{}\"", it.escape_ascii()),
|
Literal::ByteString(it) => w!(self, "\"{}\"", it.escape_ascii()),
|
||||||
Literal::CString(it) => w!(self, "\"{}\\0\"", it),
|
Literal::CString(it) => w!(self, "\"{}\\0\"", it.escape_ascii()),
|
||||||
Literal::Char(it) => w!(self, "'{}'", it.escape_debug()),
|
Literal::Char(it) => w!(self, "'{}'", it.escape_debug()),
|
||||||
Literal::Bool(it) => w!(self, "{}", it),
|
Literal::Bool(it) => w!(self, "{}", it),
|
||||||
Literal::Int(i, suffix) => {
|
Literal::Int(i, suffix) => {
|
||||||
|
|
|
@ -85,7 +85,7 @@ impl fmt::Display for FloatTypeWrapper {
|
||||||
pub enum Literal {
|
pub enum Literal {
|
||||||
String(Box<str>),
|
String(Box<str>),
|
||||||
ByteString(Box<[u8]>),
|
ByteString(Box<[u8]>),
|
||||||
CString(Box<str>),
|
CString(Box<[u8]>),
|
||||||
Char(char),
|
Char(char),
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
Int(i128, Option<BuiltinInt>),
|
Int(i128, Option<BuiltinInt>),
|
||||||
|
|
|
@ -16,7 +16,8 @@ use triomphe::Arc;
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase, infer::InferenceContext, lower::ParamLoweringMode,
|
db::HirDatabase, infer::InferenceContext, lower::ParamLoweringMode,
|
||||||
mir::monomorphize_mir_body_bad, to_placeholder_idx, utils::Generics, Const, ConstData,
|
mir::monomorphize_mir_body_bad, to_placeholder_idx, utils::Generics, Const, ConstData,
|
||||||
ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, Ty, TyBuilder,
|
ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty,
|
||||||
|
TyBuilder,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError};
|
use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError};
|
||||||
|
@ -135,7 +136,7 @@ pub fn intern_const_ref(
|
||||||
ty: Ty,
|
ty: Ty,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
) -> Const {
|
) -> Const {
|
||||||
let layout = db.layout_of_ty(ty.clone(), krate);
|
let layout = db.layout_of_ty(ty.clone(), Arc::new(TraitEnvironment::empty(krate)));
|
||||||
let bytes = match value {
|
let bytes = match value {
|
||||||
LiteralConstRef::Int(i) => {
|
LiteralConstRef::Int(i) => {
|
||||||
// FIXME: We should handle failure of layout better.
|
// FIXME: We should handle failure of layout better.
|
||||||
|
@ -173,7 +174,7 @@ pub fn try_const_usize(db: &dyn HirDatabase, c: &Const) -> Option<u128> {
|
||||||
chalk_ir::ConstValue::Concrete(c) => match &c.interned {
|
chalk_ir::ConstValue::Concrete(c) => match &c.interned {
|
||||||
ConstScalar::Bytes(it, _) => Some(u128::from_le_bytes(pad16(&it, false))),
|
ConstScalar::Bytes(it, _) => Some(u128::from_le_bytes(pad16(&it, false))),
|
||||||
ConstScalar::UnevaluatedConst(c, subst) => {
|
ConstScalar::UnevaluatedConst(c, subst) => {
|
||||||
let ec = db.const_eval(*c, subst.clone()).ok()?;
|
let ec = db.const_eval(*c, subst.clone(), None).ok()?;
|
||||||
try_const_usize(db, &ec)
|
try_const_usize(db, &ec)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -186,6 +187,7 @@ pub(crate) fn const_eval_recover(
|
||||||
_: &[String],
|
_: &[String],
|
||||||
_: &GeneralConstId,
|
_: &GeneralConstId,
|
||||||
_: &Substitution,
|
_: &Substitution,
|
||||||
|
_: &Option<Arc<TraitEnvironment>>,
|
||||||
) -> Result<Const, ConstEvalError> {
|
) -> Result<Const, ConstEvalError> {
|
||||||
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
|
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
|
||||||
}
|
}
|
||||||
|
@ -210,6 +212,7 @@ pub(crate) fn const_eval_query(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
def: GeneralConstId,
|
def: GeneralConstId,
|
||||||
subst: Substitution,
|
subst: Substitution,
|
||||||
|
trait_env: Option<Arc<TraitEnvironment>>,
|
||||||
) -> Result<Const, ConstEvalError> {
|
) -> Result<Const, ConstEvalError> {
|
||||||
let body = match def {
|
let body = match def {
|
||||||
GeneralConstId::ConstId(c) => {
|
GeneralConstId::ConstId(c) => {
|
||||||
|
@ -228,7 +231,7 @@ pub(crate) fn const_eval_query(
|
||||||
}
|
}
|
||||||
GeneralConstId::InTypeConstId(c) => db.mir_body(c.into())?,
|
GeneralConstId::InTypeConstId(c) => db.mir_body(c.into())?,
|
||||||
};
|
};
|
||||||
let c = interpret_mir(db, body, false).0?;
|
let c = interpret_mir(db, body, false, trait_env).0?;
|
||||||
Ok(c)
|
Ok(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +244,7 @@ pub(crate) fn const_eval_static_query(
|
||||||
Substitution::empty(Interner),
|
Substitution::empty(Interner),
|
||||||
db.trait_environment_for_body(def.into()),
|
db.trait_environment_for_body(def.into()),
|
||||||
)?;
|
)?;
|
||||||
let c = interpret_mir(db, body, false).0?;
|
let c = interpret_mir(db, body, false, None).0?;
|
||||||
Ok(c)
|
Ok(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +271,7 @@ pub(crate) fn const_eval_discriminant_variant(
|
||||||
Substitution::empty(Interner),
|
Substitution::empty(Interner),
|
||||||
db.trait_environment_for_body(def),
|
db.trait_environment_for_body(def),
|
||||||
)?;
|
)?;
|
||||||
let c = interpret_mir(db, mir_body, false).0?;
|
let c = interpret_mir(db, mir_body, false, None).0?;
|
||||||
let c = try_const_usize(db, &c).unwrap() as i128;
|
let c = try_const_usize(db, &c).unwrap() as i128;
|
||||||
Ok(c)
|
Ok(c)
|
||||||
}
|
}
|
||||||
|
@ -293,7 +296,7 @@ pub(crate) fn eval_to_const(
|
||||||
}
|
}
|
||||||
let infer = ctx.clone().resolve_all();
|
let infer = ctx.clone().resolve_all();
|
||||||
if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, &ctx.body, &infer, expr) {
|
if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, &ctx.body, &infer, expr) {
|
||||||
if let Ok(result) = interpret_mir(db, Arc::new(mir_body), true).0 {
|
if let Ok(result) = interpret_mir(db, Arc::new(mir_body), true, None).0 {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ fn eval_goal(db: &TestDB, file_id: FileId) -> Result<Const, ConstEvalError> {
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.expect("No const named GOAL found in the test");
|
.expect("No const named GOAL found in the test");
|
||||||
db.const_eval(const_id.into(), Substitution::empty(Interner))
|
db.const_eval(const_id.into(), Substitution::empty(Interner), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1941,6 +1941,33 @@ fn dyn_trait() {
|
||||||
"#,
|
"#,
|
||||||
900,
|
900,
|
||||||
);
|
);
|
||||||
|
check_number(
|
||||||
|
r#"
|
||||||
|
//- minicore: coerce_unsized, index, slice
|
||||||
|
trait A {
|
||||||
|
fn x(&self) -> i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait B: A {}
|
||||||
|
|
||||||
|
impl A for i32 {
|
||||||
|
fn x(&self) -> i32 {
|
||||||
|
5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl B for i32 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn f(x: &dyn B) -> i32 {
|
||||||
|
x.x()
|
||||||
|
}
|
||||||
|
|
||||||
|
const GOAL: i32 = f(&2i32);
|
||||||
|
"#,
|
||||||
|
5,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2492,6 +2519,28 @@ fn const_trait_assoc() {
|
||||||
"#,
|
"#,
|
||||||
5,
|
5,
|
||||||
);
|
);
|
||||||
|
check_number(
|
||||||
|
r#"
|
||||||
|
//- minicore: size_of
|
||||||
|
//- /a/lib.rs crate:a
|
||||||
|
use core::mem::size_of;
|
||||||
|
pub struct S<T>(T);
|
||||||
|
impl<T> S<T> {
|
||||||
|
pub const X: usize = core::mem::size_of::<T>();
|
||||||
|
}
|
||||||
|
//- /main.rs crate:main deps:a
|
||||||
|
use a::{S};
|
||||||
|
trait Tr {
|
||||||
|
type Ty;
|
||||||
|
}
|
||||||
|
impl Tr for i32 {
|
||||||
|
type Ty = u64;
|
||||||
|
}
|
||||||
|
struct K<T: Tr>(<T as Tr>::Ty);
|
||||||
|
const GOAL: usize = S::<K<i32>>::X;
|
||||||
|
"#,
|
||||||
|
8,
|
||||||
|
);
|
||||||
check_number(
|
check_number(
|
||||||
r#"
|
r#"
|
||||||
struct S<T>(*mut T);
|
struct S<T>(*mut T);
|
||||||
|
|
|
@ -77,8 +77,12 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||||
|
|
||||||
#[salsa::invoke(crate::consteval::const_eval_query)]
|
#[salsa::invoke(crate::consteval::const_eval_query)]
|
||||||
#[salsa::cycle(crate::consteval::const_eval_recover)]
|
#[salsa::cycle(crate::consteval::const_eval_recover)]
|
||||||
fn const_eval(&self, def: GeneralConstId, subst: Substitution)
|
fn const_eval(
|
||||||
-> Result<Const, ConstEvalError>;
|
&self,
|
||||||
|
def: GeneralConstId,
|
||||||
|
subst: Substitution,
|
||||||
|
trait_env: Option<Arc<crate::TraitEnvironment>>,
|
||||||
|
) -> Result<Const, ConstEvalError>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::consteval::const_eval_static_query)]
|
#[salsa::invoke(crate::consteval::const_eval_static_query)]
|
||||||
#[salsa::cycle(crate::consteval::const_eval_static_recover)]
|
#[salsa::cycle(crate::consteval::const_eval_static_recover)]
|
||||||
|
@ -100,12 +104,16 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||||
&self,
|
&self,
|
||||||
def: AdtId,
|
def: AdtId,
|
||||||
subst: Substitution,
|
subst: Substitution,
|
||||||
krate: CrateId,
|
env: Arc<crate::TraitEnvironment>,
|
||||||
) -> Result<Arc<Layout>, LayoutError>;
|
) -> Result<Arc<Layout>, LayoutError>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::layout::layout_of_ty_query)]
|
#[salsa::invoke(crate::layout::layout_of_ty_query)]
|
||||||
#[salsa::cycle(crate::layout::layout_of_ty_recover)]
|
#[salsa::cycle(crate::layout::layout_of_ty_recover)]
|
||||||
fn layout_of_ty(&self, ty: Ty, krate: CrateId) -> Result<Arc<Layout>, LayoutError>;
|
fn layout_of_ty(
|
||||||
|
&self,
|
||||||
|
ty: Ty,
|
||||||
|
env: Arc<crate::TraitEnvironment>,
|
||||||
|
) -> Result<Arc<Layout>, LayoutError>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::layout::target_data_layout_query)]
|
#[salsa::invoke(crate::layout::target_data_layout_query)]
|
||||||
fn target_data_layout(&self, krate: CrateId) -> Option<Arc<TargetDataLayout>>;
|
fn target_data_layout(&self, krate: CrateId) -> Option<Arc<TargetDataLayout>>;
|
||||||
|
|
|
@ -14,13 +14,12 @@ mod case_conv;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use base_db::CrateId;
|
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
data::adt::VariantData,
|
data::adt::VariantData,
|
||||||
hir::{Pat, PatId},
|
hir::{Pat, PatId},
|
||||||
src::HasSource,
|
src::HasSource,
|
||||||
AdtId, AttrDefId, ConstId, EnumId, FunctionId, ItemContainerId, Lookup, ModuleDefId, StaticId,
|
AdtId, AttrDefId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ItemContainerId,
|
||||||
StructId,
|
Lookup, ModuleDefId, StaticId, StructId,
|
||||||
};
|
};
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
name::{AsName, Name},
|
name::{AsName, Name},
|
||||||
|
@ -44,13 +43,9 @@ mod allow {
|
||||||
pub(super) const NON_CAMEL_CASE_TYPES: &str = "non_camel_case_types";
|
pub(super) const NON_CAMEL_CASE_TYPES: &str = "non_camel_case_types";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn incorrect_case(
|
pub fn incorrect_case(db: &dyn HirDatabase, owner: ModuleDefId) -> Vec<IncorrectCase> {
|
||||||
db: &dyn HirDatabase,
|
|
||||||
krate: CrateId,
|
|
||||||
owner: ModuleDefId,
|
|
||||||
) -> Vec<IncorrectCase> {
|
|
||||||
let _p = profile::span("validate_module_item");
|
let _p = profile::span("validate_module_item");
|
||||||
let mut validator = DeclValidator::new(db, krate);
|
let mut validator = DeclValidator::new(db);
|
||||||
validator.validate_item(owner);
|
validator.validate_item(owner);
|
||||||
validator.sink
|
validator.sink
|
||||||
}
|
}
|
||||||
|
@ -120,7 +115,6 @@ pub struct IncorrectCase {
|
||||||
|
|
||||||
pub(super) struct DeclValidator<'a> {
|
pub(super) struct DeclValidator<'a> {
|
||||||
db: &'a dyn HirDatabase,
|
db: &'a dyn HirDatabase,
|
||||||
krate: CrateId,
|
|
||||||
pub(super) sink: Vec<IncorrectCase>,
|
pub(super) sink: Vec<IncorrectCase>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,8 +126,8 @@ struct Replacement {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DeclValidator<'a> {
|
impl<'a> DeclValidator<'a> {
|
||||||
pub(super) fn new(db: &'a dyn HirDatabase, krate: CrateId) -> DeclValidator<'a> {
|
pub(super) fn new(db: &'a dyn HirDatabase) -> DeclValidator<'a> {
|
||||||
DeclValidator { db, krate, sink: Vec::new() }
|
DeclValidator { db, sink: Vec::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn validate_item(&mut self, item: ModuleDefId) {
|
pub(super) fn validate_item(&mut self, item: ModuleDefId) {
|
||||||
|
@ -195,8 +189,7 @@ impl<'a> DeclValidator<'a> {
|
||||||
AttrDefId::TypeAliasId(_) => None,
|
AttrDefId::TypeAliasId(_) => None,
|
||||||
AttrDefId::GenericParamId(_) => None,
|
AttrDefId::GenericParamId(_) => None,
|
||||||
}
|
}
|
||||||
.map(|mid| self.allowed(mid, allow_name, true))
|
.is_some_and(|mid| self.allowed(mid, allow_name, true))
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_func(&mut self, func: FunctionId) {
|
fn validate_func(&mut self, func: FunctionId) {
|
||||||
|
@ -206,17 +199,7 @@ impl<'a> DeclValidator<'a> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let body = self.db.body(func.into());
|
self.validate_body_inner_items(func.into());
|
||||||
|
|
||||||
// Recursively validate inner scope items, such as static variables and constants.
|
|
||||||
for (_, block_def_map) in body.blocks(self.db.upcast()) {
|
|
||||||
for (_, module) in block_def_map.modules() {
|
|
||||||
for def_id in module.scope.declarations() {
|
|
||||||
let mut validator = DeclValidator::new(self.db, self.krate);
|
|
||||||
validator.validate_item(def_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether non-snake case identifiers are allowed for this function.
|
// Check whether non-snake case identifiers are allowed for this function.
|
||||||
if self.allowed(func.into(), allow::NON_SNAKE_CASE, false) {
|
if self.allowed(func.into(), allow::NON_SNAKE_CASE, false) {
|
||||||
|
@ -231,6 +214,8 @@ impl<'a> DeclValidator<'a> {
|
||||||
expected_case: CaseType::LowerSnakeCase,
|
expected_case: CaseType::LowerSnakeCase,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let body = self.db.body(func.into());
|
||||||
|
|
||||||
// Check the patterns inside the function body.
|
// Check the patterns inside the function body.
|
||||||
// This includes function parameters.
|
// This includes function parameters.
|
||||||
let pats_replacements = body
|
let pats_replacements = body
|
||||||
|
@ -496,6 +481,11 @@ impl<'a> DeclValidator<'a> {
|
||||||
fn validate_enum(&mut self, enum_id: EnumId) {
|
fn validate_enum(&mut self, enum_id: EnumId) {
|
||||||
let data = self.db.enum_data(enum_id);
|
let data = self.db.enum_data(enum_id);
|
||||||
|
|
||||||
|
for (local_id, _) in data.variants.iter() {
|
||||||
|
let variant_id = EnumVariantId { parent: enum_id, local_id };
|
||||||
|
self.validate_body_inner_items(variant_id.into());
|
||||||
|
}
|
||||||
|
|
||||||
// Check whether non-camel case names are allowed for this enum.
|
// Check whether non-camel case names are allowed for this enum.
|
||||||
if self.allowed(enum_id.into(), allow::NON_CAMEL_CASE_TYPES, false) {
|
if self.allowed(enum_id.into(), allow::NON_CAMEL_CASE_TYPES, false) {
|
||||||
return;
|
return;
|
||||||
|
@ -512,13 +502,11 @@ impl<'a> DeclValidator<'a> {
|
||||||
// Check the field names.
|
// Check the field names.
|
||||||
let enum_fields_replacements = data
|
let enum_fields_replacements = data
|
||||||
.variants
|
.variants
|
||||||
.iter()
|
.values()
|
||||||
.filter_map(|(_, variant)| {
|
.filter_map(|variant| {
|
||||||
Some(Replacement {
|
Some(Replacement {
|
||||||
current_name: variant.name.clone(),
|
current_name: variant.name.clone(),
|
||||||
suggested_text: to_camel_case(
|
suggested_text: to_camel_case(&variant.name.to_smol_str())?,
|
||||||
&variant.name.display(self.db.upcast()).to_string(),
|
|
||||||
)?,
|
|
||||||
expected_case: CaseType::UpperCamelCase,
|
expected_case: CaseType::UpperCamelCase,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -622,6 +610,8 @@ impl<'a> DeclValidator<'a> {
|
||||||
fn validate_const(&mut self, const_id: ConstId) {
|
fn validate_const(&mut self, const_id: ConstId) {
|
||||||
let data = self.db.const_data(const_id);
|
let data = self.db.const_data(const_id);
|
||||||
|
|
||||||
|
self.validate_body_inner_items(const_id.into());
|
||||||
|
|
||||||
if self.allowed(const_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) {
|
if self.allowed(const_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -631,7 +621,7 @@ impl<'a> DeclValidator<'a> {
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let const_name = name.display(self.db.upcast()).to_string();
|
let const_name = name.to_smol_str();
|
||||||
let replacement = if let Some(new_name) = to_upper_snake_case(&const_name) {
|
let replacement = if let Some(new_name) = to_upper_snake_case(&const_name) {
|
||||||
Replacement {
|
Replacement {
|
||||||
current_name: name.clone(),
|
current_name: name.clone(),
|
||||||
|
@ -670,13 +660,15 @@ impl<'a> DeclValidator<'a> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.validate_body_inner_items(static_id.into());
|
||||||
|
|
||||||
if self.allowed(static_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) {
|
if self.allowed(static_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = &data.name;
|
let name = &data.name;
|
||||||
|
|
||||||
let static_name = name.display(self.db.upcast()).to_string();
|
let static_name = name.to_smol_str();
|
||||||
let replacement = if let Some(new_name) = to_upper_snake_case(&static_name) {
|
let replacement = if let Some(new_name) = to_upper_snake_case(&static_name) {
|
||||||
Replacement {
|
Replacement {
|
||||||
current_name: name.clone(),
|
current_name: name.clone(),
|
||||||
|
@ -707,4 +699,17 @@ impl<'a> DeclValidator<'a> {
|
||||||
|
|
||||||
self.sink.push(diagnostic);
|
self.sink.push(diagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: We don't currently validate names within `DefWithBodyId::InTypeConstId`.
|
||||||
|
/// Recursively validates inner scope items, such as static variables and constants.
|
||||||
|
fn validate_body_inner_items(&mut self, body_id: DefWithBodyId) {
|
||||||
|
let body = self.db.body(body_id);
|
||||||
|
for (_, block_def_map) in body.blocks(self.db.upcast()) {
|
||||||
|
for (_, module) in block_def_map.modules() {
|
||||||
|
for def_id in module.scope.declarations() {
|
||||||
|
self.validate_item(def_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ use itertools::Itertools;
|
||||||
use la_arena::ArenaMap;
|
use la_arena::ArenaMap;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use stdx::never;
|
use stdx::never;
|
||||||
|
use triomphe::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
consteval::try_const_usize,
|
consteval::try_const_usize,
|
||||||
|
@ -43,7 +44,7 @@ use crate::{
|
||||||
AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Const, ConstScalar, ConstValue,
|
AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Const, ConstScalar, ConstValue,
|
||||||
DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives,
|
DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives,
|
||||||
MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar,
|
MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar,
|
||||||
Substitution, TraitRef, TraitRefExt, Ty, TyExt, WhereClause,
|
Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyExt, WhereClause,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait HirWrite: fmt::Write {
|
pub trait HirWrite: fmt::Write {
|
||||||
|
@ -454,7 +455,9 @@ fn render_const_scalar(
|
||||||
) -> Result<(), HirDisplayError> {
|
) -> Result<(), HirDisplayError> {
|
||||||
// FIXME: We need to get krate from the final callers of the hir display
|
// FIXME: We need to get krate from the final callers of the hir display
|
||||||
// infrastructure and have it here as a field on `f`.
|
// infrastructure and have it here as a field on `f`.
|
||||||
let krate = *f.db.crate_graph().crates_in_topological_order().last().unwrap();
|
let trait_env = Arc::new(TraitEnvironment::empty(
|
||||||
|
*f.db.crate_graph().crates_in_topological_order().last().unwrap(),
|
||||||
|
));
|
||||||
match ty.kind(Interner) {
|
match ty.kind(Interner) {
|
||||||
TyKind::Scalar(s) => match s {
|
TyKind::Scalar(s) => match s {
|
||||||
Scalar::Bool => write!(f, "{}", if b[0] == 0 { false } else { true }),
|
Scalar::Bool => write!(f, "{}", if b[0] == 0 { false } else { true }),
|
||||||
|
@ -497,7 +500,7 @@ fn render_const_scalar(
|
||||||
TyKind::Slice(ty) => {
|
TyKind::Slice(ty) => {
|
||||||
let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
|
let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
|
||||||
let count = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
|
let count = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
|
||||||
let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
|
let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env) else {
|
||||||
return f.write_str("<layout-error>");
|
return f.write_str("<layout-error>");
|
||||||
};
|
};
|
||||||
let size_one = layout.size.bytes_usize();
|
let size_one = layout.size.bytes_usize();
|
||||||
|
@ -523,7 +526,7 @@ fn render_const_scalar(
|
||||||
let Ok(t) = memory_map.vtable.ty(ty_id) else {
|
let Ok(t) = memory_map.vtable.ty(ty_id) else {
|
||||||
return f.write_str("<ty-missing-in-vtable-map>");
|
return f.write_str("<ty-missing-in-vtable-map>");
|
||||||
};
|
};
|
||||||
let Ok(layout) = f.db.layout_of_ty(t.clone(), krate) else {
|
let Ok(layout) = f.db.layout_of_ty(t.clone(), trait_env) else {
|
||||||
return f.write_str("<layout-error>");
|
return f.write_str("<layout-error>");
|
||||||
};
|
};
|
||||||
let size = layout.size.bytes_usize();
|
let size = layout.size.bytes_usize();
|
||||||
|
@ -555,7 +558,7 @@ fn render_const_scalar(
|
||||||
return f.write_str("<layout-error>");
|
return f.write_str("<layout-error>");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let Ok(layout) = f.db.layout_of_ty(t.clone(), krate) else {
|
let Ok(layout) = f.db.layout_of_ty(t.clone(), trait_env) else {
|
||||||
return f.write_str("<layout-error>");
|
return f.write_str("<layout-error>");
|
||||||
};
|
};
|
||||||
let size = layout.size.bytes_usize();
|
let size = layout.size.bytes_usize();
|
||||||
|
@ -567,7 +570,7 @@ fn render_const_scalar(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TyKind::Tuple(_, subst) => {
|
TyKind::Tuple(_, subst) => {
|
||||||
let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
|
let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else {
|
||||||
return f.write_str("<layout-error>");
|
return f.write_str("<layout-error>");
|
||||||
};
|
};
|
||||||
f.write_str("(")?;
|
f.write_str("(")?;
|
||||||
|
@ -580,7 +583,7 @@ fn render_const_scalar(
|
||||||
}
|
}
|
||||||
let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument
|
let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument
|
||||||
let offset = layout.fields.offset(id).bytes_usize();
|
let offset = layout.fields.offset(id).bytes_usize();
|
||||||
let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
|
let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else {
|
||||||
f.write_str("<layout-error>")?;
|
f.write_str("<layout-error>")?;
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
@ -590,7 +593,7 @@ fn render_const_scalar(
|
||||||
f.write_str(")")
|
f.write_str(")")
|
||||||
}
|
}
|
||||||
TyKind::Adt(adt, subst) => {
|
TyKind::Adt(adt, subst) => {
|
||||||
let Ok(layout) = f.db.layout_of_adt(adt.0, subst.clone(), krate) else {
|
let Ok(layout) = f.db.layout_of_adt(adt.0, subst.clone(), trait_env.clone()) else {
|
||||||
return f.write_str("<layout-error>");
|
return f.write_str("<layout-error>");
|
||||||
};
|
};
|
||||||
match adt.0 {
|
match adt.0 {
|
||||||
|
@ -602,7 +605,7 @@ fn render_const_scalar(
|
||||||
&data.variant_data,
|
&data.variant_data,
|
||||||
f,
|
f,
|
||||||
&field_types,
|
&field_types,
|
||||||
adt.0.module(f.db.upcast()).krate(),
|
f.db.trait_environment(adt.0.into()),
|
||||||
&layout,
|
&layout,
|
||||||
subst,
|
subst,
|
||||||
b,
|
b,
|
||||||
|
@ -614,7 +617,7 @@ fn render_const_scalar(
|
||||||
}
|
}
|
||||||
hir_def::AdtId::EnumId(e) => {
|
hir_def::AdtId::EnumId(e) => {
|
||||||
let Some((var_id, var_layout)) =
|
let Some((var_id, var_layout)) =
|
||||||
detect_variant_from_bytes(&layout, f.db, krate, b, e)
|
detect_variant_from_bytes(&layout, f.db, trait_env.clone(), b, e)
|
||||||
else {
|
else {
|
||||||
return f.write_str("<failed-to-detect-variant>");
|
return f.write_str("<failed-to-detect-variant>");
|
||||||
};
|
};
|
||||||
|
@ -626,7 +629,7 @@ fn render_const_scalar(
|
||||||
&data.variant_data,
|
&data.variant_data,
|
||||||
f,
|
f,
|
||||||
&field_types,
|
&field_types,
|
||||||
adt.0.module(f.db.upcast()).krate(),
|
f.db.trait_environment(adt.0.into()),
|
||||||
&var_layout,
|
&var_layout,
|
||||||
subst,
|
subst,
|
||||||
b,
|
b,
|
||||||
|
@ -645,7 +648,7 @@ fn render_const_scalar(
|
||||||
let Some(len) = try_const_usize(f.db, len) else {
|
let Some(len) = try_const_usize(f.db, len) else {
|
||||||
return f.write_str("<unknown-array-len>");
|
return f.write_str("<unknown-array-len>");
|
||||||
};
|
};
|
||||||
let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
|
let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env) else {
|
||||||
return f.write_str("<layout-error>");
|
return f.write_str("<layout-error>");
|
||||||
};
|
};
|
||||||
let size_one = layout.size.bytes_usize();
|
let size_one = layout.size.bytes_usize();
|
||||||
|
@ -684,7 +687,7 @@ fn render_variant_after_name(
|
||||||
data: &VariantData,
|
data: &VariantData,
|
||||||
f: &mut HirFormatter<'_>,
|
f: &mut HirFormatter<'_>,
|
||||||
field_types: &ArenaMap<LocalFieldId, Binders<Ty>>,
|
field_types: &ArenaMap<LocalFieldId, Binders<Ty>>,
|
||||||
krate: CrateId,
|
trait_env: Arc<TraitEnvironment>,
|
||||||
layout: &Layout,
|
layout: &Layout,
|
||||||
subst: &Substitution,
|
subst: &Substitution,
|
||||||
b: &[u8],
|
b: &[u8],
|
||||||
|
@ -695,7 +698,7 @@ fn render_variant_after_name(
|
||||||
let render_field = |f: &mut HirFormatter<'_>, id: LocalFieldId| {
|
let render_field = |f: &mut HirFormatter<'_>, id: LocalFieldId| {
|
||||||
let offset = layout.fields.offset(u32::from(id.into_raw()) as usize).bytes_usize();
|
let offset = layout.fields.offset(u32::from(id.into_raw()) as usize).bytes_usize();
|
||||||
let ty = field_types[id].clone().substitute(Interner, subst);
|
let ty = field_types[id].clone().substitute(Interner, subst);
|
||||||
let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
|
let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else {
|
||||||
return f.write_str("<layout-error>");
|
return f.write_str("<layout-error>");
|
||||||
};
|
};
|
||||||
let size = layout.size.bytes_usize();
|
let size = layout.size.bytes_usize();
|
||||||
|
|
|
@ -1665,6 +1665,7 @@ impl InferenceContext<'_> {
|
||||||
// the parameter to coerce to the expected type (for example in
|
// the parameter to coerce to the expected type (for example in
|
||||||
// `coerce_unsize_expected_type_4`).
|
// `coerce_unsize_expected_type_4`).
|
||||||
let param_ty = self.normalize_associated_types_in(param_ty);
|
let param_ty = self.normalize_associated_types_in(param_ty);
|
||||||
|
let expected_ty = self.normalize_associated_types_in(expected_ty);
|
||||||
let expected = Expectation::rvalue_hint(self, expected_ty);
|
let expected = Expectation::rvalue_hint(self, expected_ty);
|
||||||
// infer with the expected type we have...
|
// infer with the expected type we have...
|
||||||
let ty = self.infer_expr_inner(arg, &expected);
|
let ty = self.infer_expr_inner(arg, &expected);
|
||||||
|
|
|
@ -252,7 +252,8 @@ impl<'a> InferenceTable<'a> {
|
||||||
// and registering an obligation. But it needs chalk support, so we handle the most basic
|
// and registering an obligation. But it needs chalk support, so we handle the most basic
|
||||||
// case (a non associated const without generic parameters) manually.
|
// case (a non associated const without generic parameters) manually.
|
||||||
if subst.len(Interner) == 0 {
|
if subst.len(Interner) == 0 {
|
||||||
if let Ok(eval) = self.db.const_eval((*c_id).into(), subst.clone())
|
if let Ok(eval) =
|
||||||
|
self.db.const_eval((*c_id).into(), subst.clone(), None)
|
||||||
{
|
{
|
||||||
eval
|
eval
|
||||||
} else {
|
} else {
|
||||||
|
@ -785,7 +786,7 @@ impl<'a> InferenceTable<'a> {
|
||||||
crate::ConstScalar::Unknown => self.new_const_var(data.ty.clone()),
|
crate::ConstScalar::Unknown => self.new_const_var(data.ty.clone()),
|
||||||
// try to evaluate unevaluated const. Replace with new var if const eval failed.
|
// try to evaluate unevaluated const. Replace with new var if const eval failed.
|
||||||
crate::ConstScalar::UnevaluatedConst(id, subst) => {
|
crate::ConstScalar::UnevaluatedConst(id, subst) => {
|
||||||
if let Ok(eval) = self.db.const_eval(*id, subst.clone()) {
|
if let Ok(eval) = self.db.const_eval(*id, subst.clone(), None) {
|
||||||
eval
|
eval
|
||||||
} else {
|
} else {
|
||||||
self.new_const_var(data.ty.clone())
|
self.new_const_var(data.ty.clone())
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
//! Compute the binary representation of a type
|
//! Compute the binary representation of a type
|
||||||
|
|
||||||
use base_db::CrateId;
|
|
||||||
use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
|
use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
layout::{
|
layout::{
|
||||||
|
@ -61,7 +60,6 @@ pub enum LayoutError {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LayoutCx<'a> {
|
struct LayoutCx<'a> {
|
||||||
krate: CrateId,
|
|
||||||
target: &'a TargetDataLayout,
|
target: &'a TargetDataLayout,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +80,7 @@ fn layout_of_simd_ty(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
id: StructId,
|
id: StructId,
|
||||||
subst: &Substitution,
|
subst: &Substitution,
|
||||||
krate: CrateId,
|
env: Arc<TraitEnvironment>,
|
||||||
dl: &TargetDataLayout,
|
dl: &TargetDataLayout,
|
||||||
) -> Result<Arc<Layout>, LayoutError> {
|
) -> Result<Arc<Layout>, LayoutError> {
|
||||||
let fields = db.field_types(id.into());
|
let fields = db.field_types(id.into());
|
||||||
|
@ -111,7 +109,7 @@ fn layout_of_simd_ty(
|
||||||
// * the homogeneous field type and the number of fields.
|
// * the homogeneous field type and the number of fields.
|
||||||
let (e_ty, e_len, is_array) = if let TyKind::Array(e_ty, _) = f0_ty.kind(Interner) {
|
let (e_ty, e_len, is_array) = if let TyKind::Array(e_ty, _) = f0_ty.kind(Interner) {
|
||||||
// Extract the number of elements from the layout of the array field:
|
// Extract the number of elements from the layout of the array field:
|
||||||
let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), krate)?.fields else {
|
let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), env.clone())?.fields else {
|
||||||
user_error!("Array with non array layout");
|
user_error!("Array with non array layout");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -122,7 +120,7 @@ fn layout_of_simd_ty(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Compute the ABI of the element type:
|
// Compute the ABI of the element type:
|
||||||
let e_ly = db.layout_of_ty(e_ty, krate)?;
|
let e_ly = db.layout_of_ty(e_ty, env.clone())?;
|
||||||
let Abi::Scalar(e_abi) = e_ly.abi else {
|
let Abi::Scalar(e_abi) = e_ly.abi else {
|
||||||
user_error!("simd type with inner non scalar type");
|
user_error!("simd type with inner non scalar type");
|
||||||
};
|
};
|
||||||
|
@ -152,25 +150,25 @@ fn layout_of_simd_ty(
|
||||||
pub fn layout_of_ty_query(
|
pub fn layout_of_ty_query(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
ty: Ty,
|
ty: Ty,
|
||||||
krate: CrateId,
|
trait_env: Arc<TraitEnvironment>,
|
||||||
) -> Result<Arc<Layout>, LayoutError> {
|
) -> Result<Arc<Layout>, LayoutError> {
|
||||||
|
let krate = trait_env.krate;
|
||||||
let Some(target) = db.target_data_layout(krate) else {
|
let Some(target) = db.target_data_layout(krate) else {
|
||||||
return Err(LayoutError::TargetLayoutNotAvailable);
|
return Err(LayoutError::TargetLayoutNotAvailable);
|
||||||
};
|
};
|
||||||
let cx = LayoutCx { krate, target: &target };
|
let cx = LayoutCx { target: &target };
|
||||||
let dl = &*cx.current_data_layout();
|
let dl = &*cx.current_data_layout();
|
||||||
let trait_env = Arc::new(TraitEnvironment::empty(krate));
|
let ty = normalize(db, trait_env.clone(), ty.clone());
|
||||||
let ty = normalize(db, trait_env, ty.clone());
|
|
||||||
let result = match ty.kind(Interner) {
|
let result = match ty.kind(Interner) {
|
||||||
TyKind::Adt(AdtId(def), subst) => {
|
TyKind::Adt(AdtId(def), subst) => {
|
||||||
if let hir_def::AdtId::StructId(s) = def {
|
if let hir_def::AdtId::StructId(s) = def {
|
||||||
let data = db.struct_data(*s);
|
let data = db.struct_data(*s);
|
||||||
let repr = data.repr.unwrap_or_default();
|
let repr = data.repr.unwrap_or_default();
|
||||||
if repr.simd() {
|
if repr.simd() {
|
||||||
return layout_of_simd_ty(db, *s, subst, krate, &target);
|
return layout_of_simd_ty(db, *s, subst, trait_env.clone(), &target);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return db.layout_of_adt(*def, subst.clone(), krate);
|
return db.layout_of_adt(*def, subst.clone(), trait_env.clone());
|
||||||
}
|
}
|
||||||
TyKind::Scalar(s) => match s {
|
TyKind::Scalar(s) => match s {
|
||||||
chalk_ir::Scalar::Bool => Layout::scalar(
|
chalk_ir::Scalar::Bool => Layout::scalar(
|
||||||
|
@ -228,7 +226,7 @@ pub fn layout_of_ty_query(
|
||||||
|
|
||||||
let fields = tys
|
let fields = tys
|
||||||
.iter(Interner)
|
.iter(Interner)
|
||||||
.map(|k| db.layout_of_ty(k.assert_ty_ref(Interner).clone(), krate))
|
.map(|k| db.layout_of_ty(k.assert_ty_ref(Interner).clone(), trait_env.clone()))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>();
|
let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>();
|
||||||
let fields = fields.iter().collect::<Vec<_>>();
|
let fields = fields.iter().collect::<Vec<_>>();
|
||||||
|
@ -238,7 +236,7 @@ pub fn layout_of_ty_query(
|
||||||
let count = try_const_usize(db, &count).ok_or(LayoutError::UserError(
|
let count = try_const_usize(db, &count).ok_or(LayoutError::UserError(
|
||||||
"unevaluated or mistyped const generic parameter".to_string(),
|
"unevaluated or mistyped const generic parameter".to_string(),
|
||||||
))? as u64;
|
))? as u64;
|
||||||
let element = db.layout_of_ty(element.clone(), krate)?;
|
let element = db.layout_of_ty(element.clone(), trait_env.clone())?;
|
||||||
let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow)?;
|
let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow)?;
|
||||||
|
|
||||||
let abi = if count != 0 && matches!(element.abi, Abi::Uninhabited) {
|
let abi = if count != 0 && matches!(element.abi, Abi::Uninhabited) {
|
||||||
|
@ -259,7 +257,7 @@ pub fn layout_of_ty_query(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TyKind::Slice(element) => {
|
TyKind::Slice(element) => {
|
||||||
let element = db.layout_of_ty(element.clone(), krate)?;
|
let element = db.layout_of_ty(element.clone(), trait_env.clone())?;
|
||||||
Layout {
|
Layout {
|
||||||
variants: Variants::Single { index: struct_variant_idx() },
|
variants: Variants::Single { index: struct_variant_idx() },
|
||||||
fields: FieldsShape::Array { stride: element.size, count: 0 },
|
fields: FieldsShape::Array { stride: element.size, count: 0 },
|
||||||
|
@ -335,7 +333,7 @@ pub fn layout_of_ty_query(
|
||||||
match impl_trait_id {
|
match impl_trait_id {
|
||||||
crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => {
|
crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => {
|
||||||
let infer = db.infer(func.into());
|
let infer = db.infer(func.into());
|
||||||
return db.layout_of_ty(infer.type_of_rpit[idx].clone(), krate);
|
return db.layout_of_ty(infer.type_of_rpit[idx].clone(), trait_env.clone());
|
||||||
}
|
}
|
||||||
crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {
|
crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {
|
||||||
return Err(LayoutError::NotImplemented)
|
return Err(LayoutError::NotImplemented)
|
||||||
|
@ -351,7 +349,7 @@ pub fn layout_of_ty_query(
|
||||||
.map(|it| {
|
.map(|it| {
|
||||||
db.layout_of_ty(
|
db.layout_of_ty(
|
||||||
it.ty.clone().substitute(Interner, ClosureSubst(subst).parent_subst()),
|
it.ty.clone().substitute(Interner, ClosureSubst(subst).parent_subst()),
|
||||||
krate,
|
trait_env.clone(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
@ -377,7 +375,7 @@ pub fn layout_of_ty_recover(
|
||||||
_: &dyn HirDatabase,
|
_: &dyn HirDatabase,
|
||||||
_: &[String],
|
_: &[String],
|
||||||
_: &Ty,
|
_: &Ty,
|
||||||
_: &CrateId,
|
_: &Arc<TraitEnvironment>,
|
||||||
) -> Result<Arc<Layout>, LayoutError> {
|
) -> Result<Arc<Layout>, LayoutError> {
|
||||||
user_error!("infinite sized recursive type");
|
user_error!("infinite sized recursive type");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
use std::{cmp, ops::Bound};
|
use std::{cmp, ops::Bound};
|
||||||
|
|
||||||
use base_db::CrateId;
|
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
data::adt::VariantData,
|
data::adt::VariantData,
|
||||||
layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout},
|
layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout},
|
||||||
|
@ -16,7 +15,7 @@ use crate::{
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
lang_items::is_unsafe_cell,
|
lang_items::is_unsafe_cell,
|
||||||
layout::{field_ty, Layout, LayoutError, RustcEnumVariantIdx},
|
layout::{field_ty, Layout, LayoutError, RustcEnumVariantIdx},
|
||||||
Substitution,
|
Substitution, TraitEnvironment,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::LayoutCx;
|
use super::LayoutCx;
|
||||||
|
@ -29,17 +28,18 @@ pub fn layout_of_adt_query(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
def: AdtId,
|
def: AdtId,
|
||||||
subst: Substitution,
|
subst: Substitution,
|
||||||
krate: CrateId,
|
trait_env: Arc<TraitEnvironment>,
|
||||||
) -> Result<Arc<Layout>, LayoutError> {
|
) -> Result<Arc<Layout>, LayoutError> {
|
||||||
|
let krate = trait_env.krate;
|
||||||
let Some(target) = db.target_data_layout(krate) else {
|
let Some(target) = db.target_data_layout(krate) else {
|
||||||
return Err(LayoutError::TargetLayoutNotAvailable);
|
return Err(LayoutError::TargetLayoutNotAvailable);
|
||||||
};
|
};
|
||||||
let cx = LayoutCx { krate, target: &target };
|
let cx = LayoutCx { target: &target };
|
||||||
let dl = cx.current_data_layout();
|
let dl = cx.current_data_layout();
|
||||||
let handle_variant = |def: VariantId, var: &VariantData| {
|
let handle_variant = |def: VariantId, var: &VariantData| {
|
||||||
var.fields()
|
var.fields()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(fd, _)| db.layout_of_ty(field_ty(db, def, fd, &subst), cx.krate))
|
.map(|(fd, _)| db.layout_of_ty(field_ty(db, def, fd, &subst), trait_env.clone()))
|
||||||
.collect::<Result<Vec<_>, _>>()
|
.collect::<Result<Vec<_>, _>>()
|
||||||
};
|
};
|
||||||
let (variants, repr) = match def {
|
let (variants, repr) = match def {
|
||||||
|
@ -134,7 +134,7 @@ pub fn layout_of_adt_recover(
|
||||||
_: &[String],
|
_: &[String],
|
||||||
_: &AdtId,
|
_: &AdtId,
|
||||||
_: &Substitution,
|
_: &Substitution,
|
||||||
_: &CrateId,
|
_: &Arc<TraitEnvironment>,
|
||||||
) -> Result<Arc<Layout>, LayoutError> {
|
) -> Result<Arc<Layout>, LayoutError> {
|
||||||
user_error!("infinite sized recursive type");
|
user_error!("infinite sized recursive type");
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
|
||||||
);
|
);
|
||||||
|
|
||||||
let (db, file_ids) = TestDB::with_many_files(&ra_fixture);
|
let (db, file_ids) = TestDB::with_many_files(&ra_fixture);
|
||||||
let (adt_or_type_alias_id, module_id) = file_ids
|
let adt_or_type_alias_id = file_ids
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.find_map(|file_id| {
|
.find_map(|file_id| {
|
||||||
let module_id = db.module_for_file(file_id);
|
let module_id = db.module_for_file(file_id);
|
||||||
|
@ -47,7 +47,7 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
})?;
|
})?;
|
||||||
Some((adt_or_type_alias_id, module_id))
|
Some(adt_or_type_alias_id)
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let goal_ty = match adt_or_type_alias_id {
|
let goal_ty = match adt_or_type_alias_id {
|
||||||
|
@ -58,7 +58,13 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
|
||||||
db.ty(ty_id.into()).substitute(Interner, &Substitution::empty(Interner))
|
db.ty(ty_id.into()).substitute(Interner, &Substitution::empty(Interner))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
db.layout_of_ty(goal_ty, module_id.krate())
|
db.layout_of_ty(
|
||||||
|
goal_ty,
|
||||||
|
db.trait_environment(match adt_or_type_alias_id {
|
||||||
|
Either::Left(adt) => hir_def::GenericDefId::AdtId(adt),
|
||||||
|
Either::Right(ty) => hir_def::GenericDefId::TypeAliasId(ty),
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A version of `eval_goal` for types that can not be expressed in ADTs, like closures and `impl Trait`
|
/// A version of `eval_goal` for types that can not be expressed in ADTs, like closures and `impl Trait`
|
||||||
|
@ -72,7 +78,7 @@ fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
|
||||||
let module_id = db.module_for_file(file_id);
|
let module_id = db.module_for_file(file_id);
|
||||||
let def_map = module_id.def_map(&db);
|
let def_map = module_id.def_map(&db);
|
||||||
let scope = &def_map[module_id.local_id].scope;
|
let scope = &def_map[module_id.local_id].scope;
|
||||||
let adt_id = scope
|
let function_id = scope
|
||||||
.declarations()
|
.declarations()
|
||||||
.find_map(|x| match x {
|
.find_map(|x| match x {
|
||||||
hir_def::ModuleDefId::FunctionId(x) => {
|
hir_def::ModuleDefId::FunctionId(x) => {
|
||||||
|
@ -82,11 +88,11 @@ fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let hir_body = db.body(adt_id.into());
|
let hir_body = db.body(function_id.into());
|
||||||
let b = hir_body.bindings.iter().find(|x| x.1.name.to_smol_str() == "goal").unwrap().0;
|
let b = hir_body.bindings.iter().find(|x| x.1.name.to_smol_str() == "goal").unwrap().0;
|
||||||
let infer = db.infer(adt_id.into());
|
let infer = db.infer(function_id.into());
|
||||||
let goal_ty = infer.type_of_binding[b].clone();
|
let goal_ty = infer.type_of_binding[b].clone();
|
||||||
db.layout_of_ty(goal_ty, module_id.krate())
|
db.layout_of_ty(goal_ty, db.trait_environment(function_id.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
|
|
|
@ -665,13 +665,21 @@ pub fn is_dyn_method(
|
||||||
};
|
};
|
||||||
let self_ty = trait_ref.self_type_parameter(Interner);
|
let self_ty = trait_ref.self_type_parameter(Interner);
|
||||||
if let TyKind::Dyn(d) = self_ty.kind(Interner) {
|
if let TyKind::Dyn(d) = self_ty.kind(Interner) {
|
||||||
let is_my_trait_in_bounds =
|
let is_my_trait_in_bounds = d
|
||||||
d.bounds.skip_binders().as_slice(Interner).iter().any(|it| match it.skip_binders() {
|
.bounds
|
||||||
// rustc doesn't accept `impl Foo<2> for dyn Foo<5>`, so if the trait id is equal, no matter
|
.skip_binders()
|
||||||
// what the generics are, we are sure that the method is come from the vtable.
|
.as_slice(Interner)
|
||||||
WhereClause::Implemented(tr) => tr.trait_id == trait_ref.trait_id,
|
.iter()
|
||||||
_ => false,
|
.map(|it| it.skip_binders())
|
||||||
});
|
.flat_map(|it| match it {
|
||||||
|
WhereClause::Implemented(tr) => {
|
||||||
|
all_super_traits(db.upcast(), from_chalk_trait_id(tr.trait_id))
|
||||||
|
}
|
||||||
|
_ => smallvec![],
|
||||||
|
})
|
||||||
|
// rustc doesn't accept `impl Foo<2> for dyn Foo<5>`, so if the trait id is equal, no matter
|
||||||
|
// what the generics are, we are sure that the method is come from the vtable.
|
||||||
|
.any(|x| x == trait_id);
|
||||||
if is_my_trait_in_bounds {
|
if is_my_trait_in_bounds {
|
||||||
return Some(fn_params);
|
return Some(fn_params);
|
||||||
}
|
}
|
||||||
|
@ -1504,7 +1512,7 @@ fn autoderef_method_receiver(
|
||||||
ty: Ty,
|
ty: Ty,
|
||||||
) -> Vec<(Canonical<Ty>, ReceiverAdjustments)> {
|
) -> Vec<(Canonical<Ty>, ReceiverAdjustments)> {
|
||||||
let mut deref_chain: Vec<_> = Vec::new();
|
let mut deref_chain: Vec<_> = Vec::new();
|
||||||
let mut autoderef = autoderef::Autoderef::new(table, ty, true);
|
let mut autoderef = autoderef::Autoderef::new(table, ty, false);
|
||||||
while let Some((ty, derefs)) = autoderef.next() {
|
while let Some((ty, derefs)) = autoderef.next() {
|
||||||
deref_chain.push((
|
deref_chain.push((
|
||||||
autoderef.table.canonicalize(ty).value,
|
autoderef.table.canonicalize(ty).value,
|
||||||
|
|
|
@ -142,7 +142,7 @@ impl<V, T> ProjectionElem<V, T> {
|
||||||
closure_field: impl FnOnce(ClosureId, &Substitution, usize) -> Ty,
|
closure_field: impl FnOnce(ClosureId, &Substitution, usize) -> Ty,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
) -> Ty {
|
) -> Ty {
|
||||||
if matches!(base.data(Interner).kind, TyKind::Alias(_) | TyKind::AssociatedType(..)) {
|
if matches!(base.kind(Interner), TyKind::Alias(_) | TyKind::AssociatedType(..)) {
|
||||||
base = normalize(
|
base = normalize(
|
||||||
db,
|
db,
|
||||||
// FIXME: we should get this from caller
|
// FIXME: we should get this from caller
|
||||||
|
@ -151,7 +151,7 @@ impl<V, T> ProjectionElem<V, T> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
match self {
|
match self {
|
||||||
ProjectionElem::Deref => match &base.data(Interner).kind {
|
ProjectionElem::Deref => match &base.kind(Interner) {
|
||||||
TyKind::Raw(_, inner) | TyKind::Ref(_, _, inner) => inner.clone(),
|
TyKind::Raw(_, inner) | TyKind::Ref(_, _, inner) => inner.clone(),
|
||||||
TyKind::Adt(adt, subst) if is_box(db, adt.0) => {
|
TyKind::Adt(adt, subst) if is_box(db, adt.0) => {
|
||||||
subst.at(Interner, 0).assert_ty_ref(Interner).clone()
|
subst.at(Interner, 0).assert_ty_ref(Interner).clone()
|
||||||
|
@ -161,7 +161,7 @@ impl<V, T> ProjectionElem<V, T> {
|
||||||
return TyKind::Error.intern(Interner);
|
return TyKind::Error.intern(Interner);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ProjectionElem::Field(f) => match &base.data(Interner).kind {
|
ProjectionElem::Field(f) => match &base.kind(Interner) {
|
||||||
TyKind::Adt(_, subst) => {
|
TyKind::Adt(_, subst) => {
|
||||||
db.field_types(f.parent)[f.local_id].clone().substitute(Interner, subst)
|
db.field_types(f.parent)[f.local_id].clone().substitute(Interner, subst)
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ impl<V, T> ProjectionElem<V, T> {
|
||||||
return TyKind::Error.intern(Interner);
|
return TyKind::Error.intern(Interner);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ProjectionElem::TupleOrClosureField(f) => match &base.data(Interner).kind {
|
ProjectionElem::TupleOrClosureField(f) => match &base.kind(Interner) {
|
||||||
TyKind::Tuple(_, subst) => subst
|
TyKind::Tuple(_, subst) => subst
|
||||||
.as_slice(Interner)
|
.as_slice(Interner)
|
||||||
.get(*f)
|
.get(*f)
|
||||||
|
@ -187,7 +187,7 @@ impl<V, T> ProjectionElem<V, T> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Index(_) => {
|
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Index(_) => {
|
||||||
match &base.data(Interner).kind {
|
match &base.kind(Interner) {
|
||||||
TyKind::Array(inner, _) | TyKind::Slice(inner) => inner.clone(),
|
TyKind::Array(inner, _) | TyKind::Slice(inner) => inner.clone(),
|
||||||
_ => {
|
_ => {
|
||||||
never!("Overloaded index is not a projection");
|
never!("Overloaded index is not a projection");
|
||||||
|
@ -195,7 +195,7 @@ impl<V, T> ProjectionElem<V, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&ProjectionElem::Subslice { from, to } => match &base.data(Interner).kind {
|
&ProjectionElem::Subslice { from, to } => match &base.kind(Interner) {
|
||||||
TyKind::Array(inner, c) => {
|
TyKind::Array(inner, c) => {
|
||||||
let next_c = usize_const(
|
let next_c = usize_const(
|
||||||
db,
|
db,
|
||||||
|
|
|
@ -484,9 +484,10 @@ pub fn interpret_mir(
|
||||||
// a zero size, hoping that they are all outside of our current body. Even without a fix for #7434, we can
|
// a zero size, hoping that they are all outside of our current body. Even without a fix for #7434, we can
|
||||||
// (and probably should) do better here, for example by excluding bindings outside of the target expression.
|
// (and probably should) do better here, for example by excluding bindings outside of the target expression.
|
||||||
assert_placeholder_ty_is_unused: bool,
|
assert_placeholder_ty_is_unused: bool,
|
||||||
|
trait_env: Option<Arc<TraitEnvironment>>,
|
||||||
) -> (Result<Const>, String, String) {
|
) -> (Result<Const>, String, String) {
|
||||||
let ty = body.locals[return_slot()].ty.clone();
|
let ty = body.locals[return_slot()].ty.clone();
|
||||||
let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused);
|
let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env);
|
||||||
let it: Result<Const> = (|| {
|
let it: Result<Const> = (|| {
|
||||||
if evaluator.ptr_size() != std::mem::size_of::<usize>() {
|
if evaluator.ptr_size() != std::mem::size_of::<usize>() {
|
||||||
not_supported!("targets with different pointer size from host");
|
not_supported!("targets with different pointer size from host");
|
||||||
|
@ -512,9 +513,9 @@ impl Evaluator<'_> {
|
||||||
db: &'a dyn HirDatabase,
|
db: &'a dyn HirDatabase,
|
||||||
owner: DefWithBodyId,
|
owner: DefWithBodyId,
|
||||||
assert_placeholder_ty_is_unused: bool,
|
assert_placeholder_ty_is_unused: bool,
|
||||||
|
trait_env: Option<Arc<TraitEnvironment>>,
|
||||||
) -> Evaluator<'a> {
|
) -> Evaluator<'a> {
|
||||||
let crate_id = owner.module(db.upcast()).krate();
|
let crate_id = owner.module(db.upcast()).krate();
|
||||||
let trait_env = db.trait_environment_for_body(owner);
|
|
||||||
Evaluator {
|
Evaluator {
|
||||||
stack: vec![0],
|
stack: vec![0],
|
||||||
heap: vec![0],
|
heap: vec![0],
|
||||||
|
@ -524,7 +525,7 @@ impl Evaluator<'_> {
|
||||||
static_locations: HashMap::default(),
|
static_locations: HashMap::default(),
|
||||||
db,
|
db,
|
||||||
random_state: oorandom::Rand64::new(0),
|
random_state: oorandom::Rand64::new(0),
|
||||||
trait_env,
|
trait_env: trait_env.unwrap_or_else(|| db.trait_environment_for_body(owner)),
|
||||||
crate_id,
|
crate_id,
|
||||||
stdout: vec![],
|
stdout: vec![],
|
||||||
stderr: vec![],
|
stderr: vec![],
|
||||||
|
@ -634,7 +635,7 @@ impl Evaluator<'_> {
|
||||||
addr = addr.offset(ty_size * offset);
|
addr = addr.offset(ty_size * offset);
|
||||||
}
|
}
|
||||||
&ProjectionElem::Subslice { from, to } => {
|
&ProjectionElem::Subslice { from, to } => {
|
||||||
let inner_ty = match &ty.data(Interner).kind {
|
let inner_ty = match &ty.kind(Interner) {
|
||||||
TyKind::Array(inner, _) | TyKind::Slice(inner) => inner.clone(),
|
TyKind::Array(inner, _) | TyKind::Slice(inner) => inner.clone(),
|
||||||
_ => TyKind::Error.intern(Interner),
|
_ => TyKind::Error.intern(Interner),
|
||||||
};
|
};
|
||||||
|
@ -694,14 +695,14 @@ impl Evaluator<'_> {
|
||||||
}
|
}
|
||||||
let r = self
|
let r = self
|
||||||
.db
|
.db
|
||||||
.layout_of_ty(ty.clone(), self.crate_id)
|
.layout_of_ty(ty.clone(), self.trait_env.clone())
|
||||||
.map_err(|e| MirEvalError::LayoutError(e, ty.clone()))?;
|
.map_err(|e| MirEvalError::LayoutError(e, ty.clone()))?;
|
||||||
self.layout_cache.borrow_mut().insert(ty.clone(), r.clone());
|
self.layout_cache.borrow_mut().insert(ty.clone(), r.clone());
|
||||||
Ok(r)
|
Ok(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_adt(&self, adt: AdtId, subst: Substitution) -> Result<Arc<Layout>> {
|
fn layout_adt(&self, adt: AdtId, subst: Substitution) -> Result<Arc<Layout>> {
|
||||||
self.db.layout_of_adt(adt, subst.clone(), self.crate_id).map_err(|e| {
|
self.db.layout_of_adt(adt, subst.clone(), self.trait_env.clone()).map_err(|e| {
|
||||||
MirEvalError::LayoutError(e, TyKind::Adt(chalk_ir::AdtId(adt), subst).intern(Interner))
|
MirEvalError::LayoutError(e, TyKind::Adt(chalk_ir::AdtId(adt), subst).intern(Interner))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -793,7 +794,7 @@ impl Evaluator<'_> {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|it| self.operand_ty_and_eval(it, &mut locals))
|
.map(|it| self.operand_ty_and_eval(it, &mut locals))
|
||||||
.collect::<Result<Vec<_>>>()?;
|
.collect::<Result<Vec<_>>>()?;
|
||||||
let stack_frame = match &fn_ty.data(Interner).kind {
|
let stack_frame = match &fn_ty.kind(Interner) {
|
||||||
TyKind::Function(_) => {
|
TyKind::Function(_) => {
|
||||||
let bytes = self.eval_operand(func, &mut locals)?;
|
let bytes = self.eval_operand(func, &mut locals)?;
|
||||||
self.exec_fn_pointer(
|
self.exec_fn_pointer(
|
||||||
|
@ -1255,7 +1256,7 @@ impl Evaluator<'_> {
|
||||||
PointerCast::ReifyFnPointer | PointerCast::ClosureFnPointer(_) => {
|
PointerCast::ReifyFnPointer | PointerCast::ClosureFnPointer(_) => {
|
||||||
let current_ty = self.operand_ty(operand, locals)?;
|
let current_ty = self.operand_ty(operand, locals)?;
|
||||||
if let TyKind::FnDef(_, _) | TyKind::Closure(_, _) =
|
if let TyKind::FnDef(_, _) | TyKind::Closure(_, _) =
|
||||||
¤t_ty.data(Interner).kind
|
¤t_ty.kind(Interner)
|
||||||
{
|
{
|
||||||
let id = self.vtable_map.id(current_ty);
|
let id = self.vtable_map.id(current_ty);
|
||||||
let ptr_size = self.ptr_size();
|
let ptr_size = self.ptr_size();
|
||||||
|
@ -1408,8 +1409,8 @@ impl Evaluator<'_> {
|
||||||
addr: Interval,
|
addr: Interval,
|
||||||
) -> Result<IntervalOrOwned> {
|
) -> Result<IntervalOrOwned> {
|
||||||
use IntervalOrOwned::*;
|
use IntervalOrOwned::*;
|
||||||
Ok(match &target_ty.data(Interner).kind {
|
Ok(match &target_ty.kind(Interner) {
|
||||||
TyKind::Slice(_) => match ¤t_ty.data(Interner).kind {
|
TyKind::Slice(_) => match ¤t_ty.kind(Interner) {
|
||||||
TyKind::Array(_, size) => {
|
TyKind::Array(_, size) => {
|
||||||
let len = match try_const_usize(self.db, size) {
|
let len = match try_const_usize(self.db, size) {
|
||||||
None => {
|
None => {
|
||||||
|
@ -1435,7 +1436,7 @@ impl Evaluator<'_> {
|
||||||
r.extend(vtable.to_le_bytes().into_iter());
|
r.extend(vtable.to_le_bytes().into_iter());
|
||||||
Owned(r)
|
Owned(r)
|
||||||
}
|
}
|
||||||
TyKind::Adt(id, target_subst) => match ¤t_ty.data(Interner).kind {
|
TyKind::Adt(id, target_subst) => match ¤t_ty.kind(Interner) {
|
||||||
TyKind::Adt(current_id, current_subst) => {
|
TyKind::Adt(current_id, current_subst) => {
|
||||||
if id != current_id {
|
if id != current_id {
|
||||||
not_supported!("unsizing struct with different type");
|
not_supported!("unsizing struct with different type");
|
||||||
|
@ -1582,10 +1583,13 @@ impl Evaluator<'_> {
|
||||||
const_id = hir_def::GeneralConstId::ConstId(c);
|
const_id = hir_def::GeneralConstId::ConstId(c);
|
||||||
subst = s;
|
subst = s;
|
||||||
}
|
}
|
||||||
result_owner = self.db.const_eval(const_id.into(), subst).map_err(|e| {
|
result_owner = self
|
||||||
let name = const_id.name(self.db.upcast());
|
.db
|
||||||
MirEvalError::ConstEvalError(name, Box::new(e))
|
.const_eval(const_id.into(), subst, Some(self.trait_env.clone()))
|
||||||
})?;
|
.map_err(|e| {
|
||||||
|
let name = const_id.name(self.db.upcast());
|
||||||
|
MirEvalError::ConstEvalError(name, Box::new(e))
|
||||||
|
})?;
|
||||||
if let chalk_ir::ConstValue::Concrete(c) = &result_owner.data(Interner).value {
|
if let chalk_ir::ConstValue::Concrete(c) = &result_owner.data(Interner).value {
|
||||||
if let ConstScalar::Bytes(v, mm) = &c.interned {
|
if let ConstScalar::Bytes(v, mm) = &c.interned {
|
||||||
break 'b (v, mm);
|
break 'b (v, mm);
|
||||||
|
@ -1818,9 +1822,13 @@ impl Evaluator<'_> {
|
||||||
}
|
}
|
||||||
AdtId::EnumId(e) => {
|
AdtId::EnumId(e) => {
|
||||||
let layout = this.layout(ty)?;
|
let layout = this.layout(ty)?;
|
||||||
if let Some((v, l)) =
|
if let Some((v, l)) = detect_variant_from_bytes(
|
||||||
detect_variant_from_bytes(&layout, this.db, this.crate_id, bytes, e)
|
&layout,
|
||||||
{
|
this.db,
|
||||||
|
this.trait_env.clone(),
|
||||||
|
bytes,
|
||||||
|
e,
|
||||||
|
) {
|
||||||
let data = &this.db.enum_data(e).variants[v].variant_data;
|
let data = &this.db.enum_data(e).variants[v].variant_data;
|
||||||
let field_types = this
|
let field_types = this
|
||||||
.db
|
.db
|
||||||
|
@ -1931,7 +1939,7 @@ impl Evaluator<'_> {
|
||||||
) -> Result<Option<StackFrame>> {
|
) -> Result<Option<StackFrame>> {
|
||||||
let id = from_bytes!(usize, bytes.get(self)?);
|
let id = from_bytes!(usize, bytes.get(self)?);
|
||||||
let next_ty = self.vtable_map.ty(id)?.clone();
|
let next_ty = self.vtable_map.ty(id)?.clone();
|
||||||
match &next_ty.data(Interner).kind {
|
match &next_ty.kind(Interner) {
|
||||||
TyKind::FnDef(def, generic_args) => {
|
TyKind::FnDef(def, generic_args) => {
|
||||||
self.exec_fn_def(*def, generic_args, destination, args, &locals, target_bb, span)
|
self.exec_fn_def(*def, generic_args, destination, args, &locals, target_bb, span)
|
||||||
}
|
}
|
||||||
|
@ -2182,7 +2190,7 @@ impl Evaluator<'_> {
|
||||||
let size = self.size_of_sized(&func_ty, locals, "self type of fn trait")?;
|
let size = self.size_of_sized(&func_ty, locals, "self type of fn trait")?;
|
||||||
func_data = Interval { addr: Address::from_bytes(func_data.get(self)?)?, size };
|
func_data = Interval { addr: Address::from_bytes(func_data.get(self)?)?, size };
|
||||||
}
|
}
|
||||||
match &func_ty.data(Interner).kind {
|
match &func_ty.kind(Interner) {
|
||||||
TyKind::FnDef(def, subst) => {
|
TyKind::FnDef(def, subst) => {
|
||||||
return self.exec_fn_def(
|
return self.exec_fn_def(
|
||||||
*def,
|
*def,
|
||||||
|
@ -2409,7 +2417,7 @@ pub fn render_const_using_debug_impl(
|
||||||
owner: ConstId,
|
owner: ConstId,
|
||||||
c: &Const,
|
c: &Const,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let mut evaluator = Evaluator::new(db, owner.into(), false);
|
let mut evaluator = Evaluator::new(db, owner.into(), false, None);
|
||||||
let locals = &Locals {
|
let locals = &Locals {
|
||||||
ptr: ArenaMap::new(),
|
ptr: ArenaMap::new(),
|
||||||
body: db
|
body: db
|
||||||
|
|
|
@ -30,7 +30,7 @@ fn eval_main(db: &TestDB, file_id: FileId) -> Result<(String, String), MirEvalEr
|
||||||
db.trait_environment(func_id.into()),
|
db.trait_environment(func_id.into()),
|
||||||
)
|
)
|
||||||
.map_err(|e| MirEvalError::MirLowerError(func_id.into(), e))?;
|
.map_err(|e| MirEvalError::MirLowerError(func_id.into(), e))?;
|
||||||
let (result, stdout, stderr) = interpret_mir(db, body, false);
|
let (result, stdout, stderr) = interpret_mir(db, body, false, None);
|
||||||
result?;
|
result?;
|
||||||
Ok((stdout, stderr))
|
Ok((stdout, stderr))
|
||||||
}
|
}
|
||||||
|
|
|
@ -633,7 +633,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let callee_ty = self.expr_ty_after_adjustments(*callee);
|
let callee_ty = self.expr_ty_after_adjustments(*callee);
|
||||||
match &callee_ty.data(Interner).kind {
|
match &callee_ty.kind(Interner) {
|
||||||
chalk_ir::TyKind::FnDef(..) => {
|
chalk_ir::TyKind::FnDef(..) => {
|
||||||
let func = Operand::from_bytes(vec![], callee_ty.clone());
|
let func = Operand::from_bytes(vec![], callee_ty.clone());
|
||||||
self.lower_call_and_args(
|
self.lower_call_and_args(
|
||||||
|
@ -1229,7 +1229,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||||
}
|
}
|
||||||
Expr::Array(l) => match l {
|
Expr::Array(l) => match l {
|
||||||
Array::ElementList { elements, .. } => {
|
Array::ElementList { elements, .. } => {
|
||||||
let elem_ty = match &self.expr_ty_without_adjust(expr_id).data(Interner).kind {
|
let elem_ty = match &self.expr_ty_without_adjust(expr_id).kind(Interner) {
|
||||||
TyKind::Array(ty, _) => ty.clone(),
|
TyKind::Array(ty, _) => ty.clone(),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(MirLowerError::TypeError(
|
return Err(MirLowerError::TypeError(
|
||||||
|
@ -1260,7 +1260,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||||
else {
|
else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
let len = match &self.expr_ty_without_adjust(expr_id).data(Interner).kind {
|
let len = match &self.expr_ty_without_adjust(expr_id).kind(Interner) {
|
||||||
TyKind::Array(_, len) => len.clone(),
|
TyKind::Array(_, len) => len.clone(),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(MirLowerError::TypeError(
|
return Err(MirLowerError::TypeError(
|
||||||
|
@ -1341,7 +1341,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||||
fn lower_literal_to_operand(&mut self, ty: Ty, l: &Literal) -> Result<Operand> {
|
fn lower_literal_to_operand(&mut self, ty: Ty, l: &Literal) -> Result<Operand> {
|
||||||
let size = self
|
let size = self
|
||||||
.db
|
.db
|
||||||
.layout_of_ty(ty.clone(), self.owner.module(self.db.upcast()).krate())?
|
.layout_of_ty(ty.clone(), self.db.trait_environment_for_body(self.owner))?
|
||||||
.size
|
.size
|
||||||
.bytes_usize();
|
.bytes_usize();
|
||||||
let bytes = match l {
|
let bytes = match l {
|
||||||
|
@ -1355,7 +1355,6 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||||
return Ok(Operand::from_concrete_const(data, mm, ty));
|
return Ok(Operand::from_concrete_const(data, mm, ty));
|
||||||
}
|
}
|
||||||
hir_def::hir::Literal::CString(b) => {
|
hir_def::hir::Literal::CString(b) => {
|
||||||
let b = b.as_bytes();
|
|
||||||
let bytes = b.iter().copied().chain(iter::once(0)).collect::<Vec<_>>();
|
let bytes = b.iter().copied().chain(iter::once(0)).collect::<Vec<_>>();
|
||||||
|
|
||||||
let mut data = Vec::with_capacity(mem::size_of::<usize>() * 2);
|
let mut data = Vec::with_capacity(mem::size_of::<usize>() * 2);
|
||||||
|
@ -1418,7 +1417,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||||
} else {
|
} else {
|
||||||
let name = const_id.name(self.db.upcast());
|
let name = const_id.name(self.db.upcast());
|
||||||
self.db
|
self.db
|
||||||
.const_eval(const_id.into(), subst)
|
.const_eval(const_id.into(), subst, None)
|
||||||
.map_err(|e| MirLowerError::ConstEvalError(name, Box::new(e)))?
|
.map_err(|e| MirLowerError::ConstEvalError(name, Box::new(e)))?
|
||||||
};
|
};
|
||||||
Ok(Operand::Constant(c))
|
Ok(Operand::Constant(c))
|
||||||
|
|
|
@ -1236,6 +1236,27 @@ fn main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn inherent_method_ref_self_deref_raw() {
|
||||||
|
check_types(
|
||||||
|
r#"
|
||||||
|
struct Val;
|
||||||
|
|
||||||
|
impl Val {
|
||||||
|
pub fn method(&self) -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let foo: *const Val;
|
||||||
|
foo.method();
|
||||||
|
// ^^^^^^^^^^^^ {unknown}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn trait_method_deref_raw() {
|
fn trait_method_deref_raw() {
|
||||||
check_types(
|
check_types(
|
||||||
|
|
|
@ -4434,3 +4434,47 @@ fn test(v: S<i32>) {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn associated_type_in_argument() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
trait A {
|
||||||
|
fn m(&self) -> i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn x<T: B>(k: &<T as B>::Ty) {
|
||||||
|
k.m();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct X;
|
||||||
|
struct Y;
|
||||||
|
|
||||||
|
impl A for X {
|
||||||
|
fn m(&self) -> i32 {
|
||||||
|
8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl A for Y {
|
||||||
|
fn m(&self) -> i32 {
|
||||||
|
32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait B {
|
||||||
|
type Ty: A;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl B for u16 {
|
||||||
|
type Ty = X;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ttt() {
|
||||||
|
let inp = Y;
|
||||||
|
x::<u16>(&inp);
|
||||||
|
//^^^^ expected &X, got &Y
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -28,14 +28,15 @@ use intern::Interned;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use stdx::never;
|
use stdx::never;
|
||||||
|
use triomphe::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
consteval::unknown_const,
|
consteval::unknown_const,
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
layout::{Layout, TagEncoding},
|
layout::{Layout, TagEncoding},
|
||||||
mir::pad16,
|
mir::pad16,
|
||||||
ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TraitRef, TraitRefExt,
|
ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TraitEnvironment,
|
||||||
Ty, WhereClause,
|
TraitRef, TraitRefExt, Ty, WhereClause,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn fn_traits(
|
pub(crate) fn fn_traits(
|
||||||
|
@ -417,7 +418,7 @@ impl FallibleTypeFolder<Interner> for UnevaluatedConstEvaluatorFolder<'_> {
|
||||||
) -> Result<Const, Self::Error> {
|
) -> Result<Const, Self::Error> {
|
||||||
if let chalk_ir::ConstValue::Concrete(c) = &constant.data(Interner).value {
|
if let chalk_ir::ConstValue::Concrete(c) = &constant.data(Interner).value {
|
||||||
if let ConstScalar::UnevaluatedConst(id, subst) = &c.interned {
|
if let ConstScalar::UnevaluatedConst(id, subst) = &c.interned {
|
||||||
if let Ok(eval) = self.db.const_eval(*id, subst.clone()) {
|
if let Ok(eval) = self.db.const_eval(*id, subst.clone(), None) {
|
||||||
return Ok(eval);
|
return Ok(eval);
|
||||||
} else {
|
} else {
|
||||||
return Ok(unknown_const(constant.data(Interner).ty.clone()));
|
return Ok(unknown_const(constant.data(Interner).ty.clone()));
|
||||||
|
@ -431,10 +432,11 @@ impl FallibleTypeFolder<Interner> for UnevaluatedConstEvaluatorFolder<'_> {
|
||||||
pub(crate) fn detect_variant_from_bytes<'a>(
|
pub(crate) fn detect_variant_from_bytes<'a>(
|
||||||
layout: &'a Layout,
|
layout: &'a Layout,
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
krate: CrateId,
|
trait_env: Arc<TraitEnvironment>,
|
||||||
b: &[u8],
|
b: &[u8],
|
||||||
e: EnumId,
|
e: EnumId,
|
||||||
) -> Option<(LocalEnumVariantId, &'a Layout)> {
|
) -> Option<(LocalEnumVariantId, &'a Layout)> {
|
||||||
|
let krate = trait_env.krate;
|
||||||
let (var_id, var_layout) = match &layout.variants {
|
let (var_id, var_layout) = match &layout.variants {
|
||||||
hir_def::layout::Variants::Single { index } => (index.0, &*layout),
|
hir_def::layout::Variants::Single { index } => (index.0, &*layout),
|
||||||
hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => {
|
hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => {
|
||||||
|
|
|
@ -378,11 +378,6 @@ impl ModuleDef {
|
||||||
ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(),
|
ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let module = match self.module(db) {
|
|
||||||
Some(it) => it,
|
|
||||||
None => return Vec::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut acc = Vec::new();
|
let mut acc = Vec::new();
|
||||||
|
|
||||||
match self.as_def_with_body() {
|
match self.as_def_with_body() {
|
||||||
|
@ -390,7 +385,7 @@ impl ModuleDef {
|
||||||
def.diagnostics(db, &mut acc);
|
def.diagnostics(db, &mut acc);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
for diag in hir_ty::diagnostics::incorrect_case(db, module.id.krate(), id) {
|
for diag in hir_ty::diagnostics::incorrect_case(db, id) {
|
||||||
acc.push(diag.into())
|
acc.push(diag.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -965,8 +960,15 @@ impl Field {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
||||||
db.layout_of_ty(self.ty(db).ty.clone(), self.parent.module(db).krate().into())
|
db.layout_of_ty(
|
||||||
.map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap()))
|
self.ty(db).ty.clone(),
|
||||||
|
db.trait_environment(match hir_def::VariantId::from(self.parent) {
|
||||||
|
hir_def::VariantId::EnumVariantId(id) => GenericDefId::EnumVariantId(id),
|
||||||
|
hir_def::VariantId::StructId(id) => GenericDefId::AdtId(id.into()),
|
||||||
|
hir_def::VariantId::UnionId(id) => GenericDefId::AdtId(id.into()),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
|
pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
|
||||||
|
@ -1246,8 +1248,12 @@ impl Adt {
|
||||||
return Err(LayoutError::HasPlaceholder);
|
return Err(LayoutError::HasPlaceholder);
|
||||||
}
|
}
|
||||||
let krate = self.krate(db).id;
|
let krate = self.krate(db).id;
|
||||||
db.layout_of_adt(self.into(), Substitution::empty(Interner), krate)
|
db.layout_of_adt(
|
||||||
.map(|layout| Layout(layout, db.target_data_layout(krate).unwrap()))
|
self.into(),
|
||||||
|
Substitution::empty(Interner),
|
||||||
|
db.trait_environment(self.into()),
|
||||||
|
)
|
||||||
|
.map(|layout| Layout(layout, db.target_data_layout(krate).unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Turns this ADT into a type. Any type parameters of the ADT will be
|
/// Turns this ADT into a type. Any type parameters of the ADT will be
|
||||||
|
@ -1820,7 +1826,7 @@ impl DefWithBody {
|
||||||
// FIXME: don't ignore diagnostics for in type const
|
// FIXME: don't ignore diagnostics for in type const
|
||||||
DefWithBody::InTypeConst(_) => return,
|
DefWithBody::InTypeConst(_) => return,
|
||||||
};
|
};
|
||||||
for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) {
|
for diag in hir_ty::diagnostics::incorrect_case(db, def.into()) {
|
||||||
acc.push(diag.into())
|
acc.push(diag.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1987,7 +1993,7 @@ impl Function {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let (result, stdout, stderr) = interpret_mir(db, body, false);
|
let (result, stdout, stderr) = interpret_mir(db, body, false, None);
|
||||||
let mut text = match result {
|
let mut text = match result {
|
||||||
Ok(_) => "pass".to_string(),
|
Ok(_) => "pass".to_string(),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -2156,7 +2162,7 @@ impl Const {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError> {
|
pub fn render_eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError> {
|
||||||
let c = db.const_eval(self.id.into(), Substitution::empty(Interner))?;
|
let c = db.const_eval(self.id.into(), Substitution::empty(Interner), None)?;
|
||||||
let data = &c.data(Interner);
|
let data = &c.data(Interner);
|
||||||
if let TyKind::Scalar(s) = data.ty.kind(Interner) {
|
if let TyKind::Scalar(s) = data.ty.kind(Interner) {
|
||||||
if matches!(s, Scalar::Int(_) | Scalar::Uint(_)) {
|
if matches!(s, Scalar::Int(_) | Scalar::Uint(_)) {
|
||||||
|
@ -4322,7 +4328,7 @@ impl Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
||||||
db.layout_of_ty(self.ty.clone(), self.env.krate)
|
db.layout_of_ty(self.ty.clone(), self.env.clone())
|
||||||
.map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap()))
|
.map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,10 @@ use syntax::{
|
||||||
ast::{self, HasName, HasVisibility},
|
ast::{self, HasName, HasVisibility},
|
||||||
AstNode,
|
AstNode,
|
||||||
SyntaxKind::{
|
SyntaxKind::{
|
||||||
CONST, ENUM, FN, MACRO_DEF, MODULE, STATIC, STRUCT, TRAIT, TYPE_ALIAS, USE, VISIBILITY,
|
self, ASSOC_ITEM_LIST, CONST, ENUM, FN, MACRO_DEF, MODULE, SOURCE_FILE, STATIC, STRUCT,
|
||||||
|
TRAIT, TYPE_ALIAS, USE, VISIBILITY,
|
||||||
},
|
},
|
||||||
T,
|
SyntaxNode, T,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists};
|
use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists};
|
||||||
|
@ -46,13 +47,11 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
|
||||||
|
|
||||||
let (offset, target) = if let Some(keyword) = item_keyword {
|
let (offset, target) = if let Some(keyword) = item_keyword {
|
||||||
let parent = keyword.parent()?;
|
let parent = keyword.parent()?;
|
||||||
let def_kws =
|
|
||||||
vec![CONST, STATIC, TYPE_ALIAS, FN, MODULE, STRUCT, ENUM, TRAIT, USE, MACRO_DEF];
|
if !can_add(&parent) {
|
||||||
// Parent is not a definition, can't add visibility
|
|
||||||
if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) {
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
// Already have visibility, do nothing
|
// Already has visibility, do nothing
|
||||||
if parent.children().any(|child| child.kind() == VISIBILITY) {
|
if parent.children().any(|child| child.kind() == VISIBILITY) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -86,6 +85,29 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn can_add(node: &SyntaxNode) -> bool {
|
||||||
|
const LEGAL: &[SyntaxKind] =
|
||||||
|
&[CONST, STATIC, TYPE_ALIAS, FN, MODULE, STRUCT, ENUM, TRAIT, USE, MACRO_DEF];
|
||||||
|
|
||||||
|
LEGAL.contains(&node.kind()) && {
|
||||||
|
let Some(p) = node.parent() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if p.kind() == ASSOC_ITEM_LIST {
|
||||||
|
p.parent()
|
||||||
|
.and_then(|it| ast::Impl::cast(it))
|
||||||
|
// inherent impls i.e 'non-trait impls' have a non-local
|
||||||
|
// effect, thus can have visibility even when nested.
|
||||||
|
// so filter them out
|
||||||
|
.filter(|imp| imp.for_token().is_none())
|
||||||
|
.is_some()
|
||||||
|
} else {
|
||||||
|
matches!(p.kind(), SOURCE_FILE | MODULE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> {
|
fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> {
|
||||||
if vis.syntax().text() == "pub" {
|
if vis.syntax().text() == "pub" {
|
||||||
let target = vis.syntax().text_range();
|
let target = vis.syntax().text_range();
|
||||||
|
@ -129,6 +151,16 @@ mod tests {
|
||||||
check_assist(change_visibility, "unsafe f$0n foo() {}", "pub(crate) unsafe fn foo() {}");
|
check_assist(change_visibility, "unsafe f$0n foo() {}", "pub(crate) unsafe fn foo() {}");
|
||||||
check_assist(change_visibility, "$0macro foo() {}", "pub(crate) macro foo() {}");
|
check_assist(change_visibility, "$0macro foo() {}", "pub(crate) macro foo() {}");
|
||||||
check_assist(change_visibility, "$0use foo;", "pub(crate) use foo;");
|
check_assist(change_visibility, "$0use foo;", "pub(crate) use foo;");
|
||||||
|
check_assist(
|
||||||
|
change_visibility,
|
||||||
|
"impl Foo { f$0n foo() {} }",
|
||||||
|
"impl Foo { pub(crate) fn foo() {} }",
|
||||||
|
);
|
||||||
|
check_assist(
|
||||||
|
change_visibility,
|
||||||
|
"fn bar() { impl Foo { f$0n foo() {} } }",
|
||||||
|
"fn bar() { impl Foo { pub(crate) fn foo() {} } }",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -213,4 +245,33 @@ mod tests {
|
||||||
check_assist_target(change_visibility, "pub(crate)$0 fn foo() {}", "pub(crate)");
|
check_assist_target(change_visibility, "pub(crate)$0 fn foo() {}", "pub(crate)");
|
||||||
check_assist_target(change_visibility, "struct S { $0field: u32 }", "field");
|
check_assist_target(change_visibility, "struct S { $0field: u32 }", "field");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn not_applicable_for_items_within_traits() {
|
||||||
|
check_assist_not_applicable(change_visibility, "trait Foo { f$0n run() {} }");
|
||||||
|
check_assist_not_applicable(change_visibility, "trait Foo { con$0st FOO: u8 = 69; }");
|
||||||
|
check_assist_not_applicable(change_visibility, "impl Foo for Bar { f$0n quox() {} }");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn not_applicable_for_items_within_fns() {
|
||||||
|
check_assist_not_applicable(change_visibility, "fn foo() { f$0n inner() {} }");
|
||||||
|
check_assist_not_applicable(change_visibility, "fn foo() { unsafe f$0n inner() {} }");
|
||||||
|
check_assist_not_applicable(change_visibility, "fn foo() { const f$0n inner() {} }");
|
||||||
|
check_assist_not_applicable(change_visibility, "fn foo() { con$0st FOO: u8 = 69; }");
|
||||||
|
check_assist_not_applicable(change_visibility, "fn foo() { en$0um Foo {} }");
|
||||||
|
check_assist_not_applicable(change_visibility, "fn foo() { stru$0ct Foo {} }");
|
||||||
|
check_assist_not_applicable(change_visibility, "fn foo() { mo$0d foo {} }");
|
||||||
|
check_assist_not_applicable(change_visibility, "fn foo() { $0use foo; }");
|
||||||
|
check_assist_not_applicable(change_visibility, "fn foo() { $0type Foo = Bar<T>; }");
|
||||||
|
check_assist_not_applicable(change_visibility, "fn foo() { tr$0ait Foo {} }");
|
||||||
|
check_assist_not_applicable(
|
||||||
|
change_visibility,
|
||||||
|
"fn foo() { impl Trait for Bar { f$0n bar() {} } }",
|
||||||
|
);
|
||||||
|
check_assist_not_applicable(
|
||||||
|
change_visibility,
|
||||||
|
"fn foo() { impl Trait for Bar { con$0st FOO: u8 = 69; } }",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -545,4 +545,100 @@ pub static SomeStatic: u8 = 10;
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fn_inner_items() {
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
fn main() {
|
||||||
|
const foo: bool = true;
|
||||||
|
//^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
|
||||||
|
static bar: bool = true;
|
||||||
|
//^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
|
||||||
|
fn BAZ() {
|
||||||
|
//^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
|
||||||
|
const foo: bool = true;
|
||||||
|
//^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
|
||||||
|
static bar: bool = true;
|
||||||
|
//^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
|
||||||
|
fn BAZ() {
|
||||||
|
//^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
|
||||||
|
let INNER_INNER = 42;
|
||||||
|
//^^^^^^^^^^^ 💡 warn: Variable `INNER_INNER` should have snake_case name, e.g. `inner_inner`
|
||||||
|
}
|
||||||
|
|
||||||
|
let INNER_LOCAL = 42;
|
||||||
|
//^^^^^^^^^^^ 💡 warn: Variable `INNER_LOCAL` should have snake_case name, e.g. `inner_local`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn const_body_inner_items() {
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
const _: () = {
|
||||||
|
static bar: bool = true;
|
||||||
|
//^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
|
||||||
|
fn BAZ() {}
|
||||||
|
//^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
|
||||||
|
|
||||||
|
const foo: () = {
|
||||||
|
//^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
|
||||||
|
const foo: bool = true;
|
||||||
|
//^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
|
||||||
|
static bar: bool = true;
|
||||||
|
//^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
|
||||||
|
fn BAZ() {}
|
||||||
|
//^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn static_body_inner_items() {
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
static FOO: () = {
|
||||||
|
const foo: bool = true;
|
||||||
|
//^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
|
||||||
|
fn BAZ() {}
|
||||||
|
//^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
|
||||||
|
|
||||||
|
static bar: () = {
|
||||||
|
//^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
|
||||||
|
const foo: bool = true;
|
||||||
|
//^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
|
||||||
|
static bar: bool = true;
|
||||||
|
//^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
|
||||||
|
fn BAZ() {}
|
||||||
|
//^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn enum_variant_body_inner_item() {
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
enum E {
|
||||||
|
A = {
|
||||||
|
const foo: bool = true;
|
||||||
|
//^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
|
||||||
|
static bar: bool = true;
|
||||||
|
//^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
|
||||||
|
fn BAZ() {}
|
||||||
|
//^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
|
||||||
|
42
|
||||||
|
},
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ use syntax::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
syntax_highlighting::{
|
syntax_highlighting::{
|
||||||
escape::{highlight_escape_char, highlight_escape_string},
|
escape::{highlight_escape_byte, highlight_escape_char, highlight_escape_string},
|
||||||
format::highlight_format_string,
|
format::highlight_format_string,
|
||||||
highlights::Highlights,
|
highlights::Highlights,
|
||||||
macro_::MacroHighlighter,
|
macro_::MacroHighlighter,
|
||||||
|
@ -471,6 +471,14 @@ fn traverse(
|
||||||
};
|
};
|
||||||
|
|
||||||
highlight_escape_char(hl, &char, range.start())
|
highlight_escape_char(hl, &char, range.start())
|
||||||
|
} else if ast::Byte::can_cast(token.kind())
|
||||||
|
&& ast::Byte::can_cast(descended_token.kind())
|
||||||
|
{
|
||||||
|
let Some(byte) = ast::Byte::cast(token) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
highlight_escape_byte(hl, &byte, range.start())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Syntax highlighting for escape sequences
|
//! Syntax highlighting for escape sequences
|
||||||
use crate::syntax_highlighting::highlights::Highlights;
|
use crate::syntax_highlighting::highlights::Highlights;
|
||||||
use crate::{HlRange, HlTag};
|
use crate::{HlRange, HlTag};
|
||||||
use syntax::ast::{Char, IsString};
|
use syntax::ast::{Byte, Char, IsString};
|
||||||
use syntax::{AstToken, TextRange, TextSize};
|
use syntax::{AstToken, TextRange, TextSize};
|
||||||
|
|
||||||
pub(super) fn highlight_escape_string<T: IsString>(
|
pub(super) fn highlight_escape_string<T: IsString>(
|
||||||
|
@ -10,14 +10,14 @@ pub(super) fn highlight_escape_string<T: IsString>(
|
||||||
start: TextSize,
|
start: TextSize,
|
||||||
) {
|
) {
|
||||||
string.escaped_char_ranges(&mut |piece_range, char| {
|
string.escaped_char_ranges(&mut |piece_range, char| {
|
||||||
if char.is_err() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if string.text()[piece_range.start().into()..].starts_with('\\') {
|
if string.text()[piece_range.start().into()..].starts_with('\\') {
|
||||||
|
let highlight = match char {
|
||||||
|
Ok(_) => HlTag::EscapeSequence,
|
||||||
|
Err(_) => HlTag::InvalidEscapeSequence,
|
||||||
|
};
|
||||||
stack.add(HlRange {
|
stack.add(HlRange {
|
||||||
range: piece_range + start,
|
range: piece_range + start,
|
||||||
highlight: HlTag::EscapeSequence.into(),
|
highlight: highlight.into(),
|
||||||
binding_hash: None,
|
binding_hash: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,9 @@ pub(super) fn highlight_escape_string<T: IsString>(
|
||||||
|
|
||||||
pub(super) fn highlight_escape_char(stack: &mut Highlights, char: &Char, start: TextSize) {
|
pub(super) fn highlight_escape_char(stack: &mut Highlights, char: &Char, start: TextSize) {
|
||||||
if char.value().is_none() {
|
if char.value().is_none() {
|
||||||
|
// We do not emit invalid escapes highlighting here. The lexer would likely be in a bad
|
||||||
|
// state and this token contains junks, since `'` is not a reliable delimiter (consider
|
||||||
|
// lifetimes). Nonetheless, parser errors should already be emitted.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,3 +46,24 @@ pub(super) fn highlight_escape_char(stack: &mut Highlights, char: &Char, start:
|
||||||
TextRange::new(start + TextSize::from(1), start + TextSize::from(text.len() as u32 + 1));
|
TextRange::new(start + TextSize::from(1), start + TextSize::from(text.len() as u32 + 1));
|
||||||
stack.add(HlRange { range, highlight: HlTag::EscapeSequence.into(), binding_hash: None })
|
stack.add(HlRange { range, highlight: HlTag::EscapeSequence.into(), binding_hash: None })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn highlight_escape_byte(stack: &mut Highlights, byte: &Byte, start: TextSize) {
|
||||||
|
if byte.value().is_none() {
|
||||||
|
// See `highlight_escape_char` for why no error highlighting here.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = byte.text();
|
||||||
|
if !text.starts_with("b'") || !text.ends_with('\'') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = &text[2..text.len() - 1];
|
||||||
|
if !text.starts_with('\\') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let range =
|
||||||
|
TextRange::new(start + TextSize::from(2), start + TextSize::from(text.len() as u32 + 2));
|
||||||
|
stack.add(HlRange { range, highlight: HlTag::EscapeSequence.into(), binding_hash: None })
|
||||||
|
}
|
||||||
|
|
|
@ -109,6 +109,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
";
|
";
|
||||||
|
|
|
@ -29,6 +29,7 @@ pub enum HlTag {
|
||||||
Comment,
|
Comment,
|
||||||
EscapeSequence,
|
EscapeSequence,
|
||||||
FormatSpecifier,
|
FormatSpecifier,
|
||||||
|
InvalidEscapeSequence,
|
||||||
Keyword,
|
Keyword,
|
||||||
NumericLiteral,
|
NumericLiteral,
|
||||||
Operator(HlOperator),
|
Operator(HlOperator),
|
||||||
|
@ -166,6 +167,7 @@ impl HlTag {
|
||||||
HlTag::CharLiteral => "char_literal",
|
HlTag::CharLiteral => "char_literal",
|
||||||
HlTag::Comment => "comment",
|
HlTag::Comment => "comment",
|
||||||
HlTag::EscapeSequence => "escape_sequence",
|
HlTag::EscapeSequence => "escape_sequence",
|
||||||
|
HlTag::InvalidEscapeSequence => "invalid_escape_sequence",
|
||||||
HlTag::FormatSpecifier => "format_specifier",
|
HlTag::FormatSpecifier => "format_specifier",
|
||||||
HlTag::Keyword => "keyword",
|
HlTag::Keyword => "keyword",
|
||||||
HlTag::Punctuation(punct) => match punct {
|
HlTag::Punctuation(punct) => match punct {
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="keyword">fn</span> <span class="function declaration">not_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
|
<pre><code><span class="keyword">fn</span> <span class="function declaration">not_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">allow</span><span class="parenthesis attribute">(</span><span class="none attribute">dead_code</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
|
<pre><code><span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">allow</span><span class="parenthesis attribute">(</span><span class="none attribute">dead_code</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
|
||||||
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="tool_module attribute library">rustfmt</span><span class="operator attribute">::</span><span class="tool_module attribute library">skip</span><span class="attribute_bracket attribute">]</span>
|
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="tool_module attribute library">rustfmt</span><span class="operator attribute">::</span><span class="tool_module attribute library">skip</span><span class="attribute_bracket attribute">]</span>
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root library">foo</span><span class="semicolon">;</span>
|
<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root library">foo</span><span class="semicolon">;</span>
|
||||||
<span class="keyword">use</span> <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">iter</span><span class="semicolon">;</span>
|
<span class="keyword">use</span> <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">iter</span><span class="semicolon">;</span>
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="keyword">use</span> <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">iter</span><span class="semicolon">;</span>
|
<pre><code><span class="keyword">use</span> <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">iter</span><span class="semicolon">;</span>
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="comment documentation">//! This is a module to test doc injection.</span>
|
<pre><code><span class="comment documentation">//! This is a module to test doc injection.</span>
|
||||||
<span class="comment documentation">//! ```</span>
|
<span class="comment documentation">//! ```</span>
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">std</span><span class="semicolon">;</span>
|
<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">std</span><span class="semicolon">;</span>
|
||||||
<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">alloc</span> <span class="keyword">as</span> <span class="module crate_root default_library declaration library">abc</span><span class="semicolon">;</span>
|
<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">alloc</span> <span class="keyword">as</span> <span class="module crate_root default_library declaration library">abc</span><span class="semicolon">;</span>
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="brace">}</span><span class="semicolon">;</span>
|
<pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="brace">}</span><span class="semicolon">;</span>
|
||||||
<span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span><span class="brace">}</span>
|
<span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span><span class="brace">}</span>
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="keyword">fn</span> <span class="function declaration">fixture</span><span class="parenthesis">(</span><span class="value_param declaration reference">ra_fixture</span><span class="colon">:</span> <span class="punctuation">&</span><span class="builtin_type">str</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
|
<pre><code><span class="keyword">fn</span> <span class="function declaration">fixture</span><span class="parenthesis">(</span><span class="value_param declaration reference">ra_fixture</span><span class="colon">:</span> <span class="punctuation">&</span><span class="builtin_type">str</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="self_keyword crate_root public">self</span><span class="semicolon">;</span>
|
<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="self_keyword crate_root public">self</span><span class="semicolon">;</span>
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code>
|
<pre><code>
|
||||||
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
|
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="module crate_root library">proc_macros</span><span class="operator">::</span><span class="macro library">mirror</span><span class="macro_bang">!</span> <span class="brace macro">{</span>
|
<pre><code><span class="module crate_root library">proc_macros</span><span class="operator">::</span><span class="macro library">mirror</span><span class="macro_bang">!</span> <span class="brace macro">{</span>
|
||||||
<span class="brace macro">{</span>
|
<span class="brace macro">{</span>
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="comment documentation">//! </span><span class="struct documentation injected intra_doc_link">[Struct]</span>
|
<pre><code><span class="comment documentation">//! </span><span class="struct documentation injected intra_doc_link">[Struct]</span>
|
||||||
<span class="comment documentation">//! This is an intra doc injection test for modules</span>
|
<span class="comment documentation">//! This is an intra doc injection test for modules</span>
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="comment documentation">/// </span><span class="struct documentation injected intra_doc_link">[crate::foo::Struct]</span>
|
<pre><code><span class="comment documentation">/// </span><span class="struct documentation injected intra_doc_link">[crate::foo::Struct]</span>
|
||||||
<span class="comment documentation">/// This is an intra doc injection test for modules</span>
|
<span class="comment documentation">/// This is an intra doc injection test for modules</span>
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
|
<pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
|
||||||
<span class="numeric_literal">1</span> <span class="arithmetic">+</span> <span class="numeric_literal">1</span> <span class="arithmetic">-</span> <span class="numeric_literal">1</span> <span class="arithmetic">*</span> <span class="numeric_literal">1</span> <span class="arithmetic">/</span> <span class="numeric_literal">1</span> <span class="arithmetic">%</span> <span class="numeric_literal">1</span> <span class="bitwise">|</span> <span class="numeric_literal">1</span> <span class="bitwise">&</span> <span class="numeric_literal">1</span> <span class="logical">!</span> <span class="numeric_literal">1</span> <span class="bitwise">^</span> <span class="numeric_literal">1</span> <span class="bitwise">>></span> <span class="numeric_literal">1</span> <span class="bitwise"><<</span> <span class="numeric_literal">1</span><span class="semicolon">;</span>
|
<span class="numeric_literal">1</span> <span class="arithmetic">+</span> <span class="numeric_literal">1</span> <span class="arithmetic">-</span> <span class="numeric_literal">1</span> <span class="arithmetic">*</span> <span class="numeric_literal">1</span> <span class="arithmetic">/</span> <span class="numeric_literal">1</span> <span class="arithmetic">%</span> <span class="numeric_literal">1</span> <span class="bitwise">|</span> <span class="numeric_literal">1</span> <span class="bitwise">&</span> <span class="numeric_literal">1</span> <span class="logical">!</span> <span class="numeric_literal">1</span> <span class="bitwise">^</span> <span class="numeric_literal">1</span> <span class="bitwise">>></span> <span class="numeric_literal">1</span> <span class="bitwise"><<</span> <span class="numeric_literal">1</span><span class="semicolon">;</span>
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
|
<pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
|
||||||
<span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
|
<span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">println</span> <span class="brace">{</span>
|
<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">println</span> <span class="brace">{</span>
|
||||||
<span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">></span> <span class="parenthesis">(</span><span class="brace">{</span>
|
<span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">></span> <span class="parenthesis">(</span><span class="brace">{</span>
|
||||||
|
@ -105,6 +106,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
<span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="char_literal">'</span><span class="escape_sequence">\x65</span><span class="char_literal">'</span><span class="semicolon">;</span>
|
<span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="char_literal">'</span><span class="escape_sequence">\x65</span><span class="char_literal">'</span><span class="semicolon">;</span>
|
||||||
<span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="char_literal">'</span><span class="escape_sequence">\x00</span><span class="char_literal">'</span><span class="semicolon">;</span>
|
<span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="char_literal">'</span><span class="escape_sequence">\x00</span><span class="char_literal">'</span><span class="semicolon">;</span>
|
||||||
|
|
||||||
|
<span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="byte_literal">b'</span><span class="escape_sequence">\xFF</span><span class="byte_literal">'</span><span class="semicolon">;</span>
|
||||||
|
|
||||||
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="comment">// from https://doc.rust-lang.org/std/fmt/index.html</span>
|
<span class="comment">// from https://doc.rust-lang.org/std/fmt/index.html</span>
|
||||||
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "Hello"</span>
|
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "Hello"</span>
|
||||||
|
@ -159,8 +162,9 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello</span><span class="escape_sequence">\n</span><span class="string_literal macro">World"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello</span><span class="escape_sequence">\n</span><span class="string_literal macro">World"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">\u{48}</span><span class="escape_sequence">\x65</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6F</span><span class="string_literal macro"> World"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">\u{48}</span><span class="escape_sequence">\x65</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6F</span><span class="string_literal macro"> World"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
|
|
||||||
<span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span>
|
<span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="invalid_escape_sequence">\xFF</span><span class="escape_sequence">\u{FF}</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// invalid non-UTF8 escape sequences</span>
|
||||||
<span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">b"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span>
|
<span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">b"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="escape_sequence">\xFF</span><span class="invalid_escape_sequence">\u{FF}</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// valid bytes, invalid unicodes</span>
|
||||||
|
<span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">c"</span><span class="escape_sequence">\u{FF}</span><span class="escape_sequence">\xFF</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// valid bytes, valid unicodes</span>
|
||||||
<span class="keyword">let</span> <span class="variable declaration reference">backslash</span> <span class="operator">=</span> <span class="string_literal">r"\\"</span><span class="semicolon">;</span>
|
<span class="keyword">let</span> <span class="variable declaration reference">backslash</span> <span class="operator">=</span> <span class="string_literal">r"\\"</span><span class="semicolon">;</span>
|
||||||
|
|
||||||
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">A</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">A</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
|
|
|
@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
.reference { font-style: italic; font-weight: bold; }
|
.reference { font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">id</span> <span class="brace">{</span>
|
<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">id</span> <span class="brace">{</span>
|
||||||
<span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">></span> <span class="brace">{</span>
|
<span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">></span> <span class="brace">{</span>
|
||||||
|
|
|
@ -451,6 +451,8 @@ fn main() {
|
||||||
let a = '\x65';
|
let a = '\x65';
|
||||||
let a = '\x00';
|
let a = '\x00';
|
||||||
|
|
||||||
|
let a = b'\xFF';
|
||||||
|
|
||||||
println!("Hello {{Hello}}");
|
println!("Hello {{Hello}}");
|
||||||
// from https://doc.rust-lang.org/std/fmt/index.html
|
// from https://doc.rust-lang.org/std/fmt/index.html
|
||||||
println!("Hello"); // => "Hello"
|
println!("Hello"); // => "Hello"
|
||||||
|
@ -505,8 +507,9 @@ fn main() {
|
||||||
println!("Hello\nWorld");
|
println!("Hello\nWorld");
|
||||||
println!("\u{48}\x65\x6C\x6C\x6F World");
|
println!("\u{48}\x65\x6C\x6C\x6F World");
|
||||||
|
|
||||||
let _ = "\x28\x28\x00\x63\n";
|
let _ = "\x28\x28\x00\x63\xFF\u{FF}\n"; // invalid non-UTF8 escape sequences
|
||||||
let _ = b"\x28\x28\x00\x63\n";
|
let _ = b"\x28\x28\x00\x63\xFF\u{FF}\n"; // valid bytes, invalid unicodes
|
||||||
|
let _ = c"\u{FF}\xFF"; // valid bytes, valid unicodes
|
||||||
let backslash = r"\\";
|
let backslash = r"\\";
|
||||||
|
|
||||||
println!("{\x41}", A = 92);
|
println!("{\x41}", A = 92);
|
||||||
|
|
|
@ -211,70 +211,54 @@ impl BlockLike {
|
||||||
const VISIBILITY_FIRST: TokenSet = TokenSet::new(&[T![pub], T![crate]]);
|
const VISIBILITY_FIRST: TokenSet = TokenSet::new(&[T![pub], T![crate]]);
|
||||||
|
|
||||||
fn opt_visibility(p: &mut Parser<'_>, in_tuple_field: bool) -> bool {
|
fn opt_visibility(p: &mut Parser<'_>, in_tuple_field: bool) -> bool {
|
||||||
match p.current() {
|
if !p.at(T![pub]) {
|
||||||
T![pub] => {
|
return false;
|
||||||
let m = p.start();
|
}
|
||||||
p.bump(T![pub]);
|
|
||||||
if p.at(T!['(']) {
|
|
||||||
match p.nth(1) {
|
|
||||||
// test crate_visibility
|
|
||||||
// pub(crate) struct S;
|
|
||||||
// pub(self) struct S;
|
|
||||||
// pub(super) struct S;
|
|
||||||
|
|
||||||
// test_err crate_visibility_empty_recover
|
let m = p.start();
|
||||||
// pub() struct S;
|
p.bump(T![pub]);
|
||||||
|
if p.at(T!['(']) {
|
||||||
|
match p.nth(1) {
|
||||||
|
// test crate_visibility
|
||||||
|
// pub(crate) struct S;
|
||||||
|
// pub(self) struct S;
|
||||||
|
// pub(super) struct S;
|
||||||
|
|
||||||
// test pub_parens_typepath
|
// test_err crate_visibility_empty_recover
|
||||||
// struct B(pub (super::A));
|
// pub() struct S;
|
||||||
// struct B(pub (crate::A,));
|
|
||||||
T![crate] | T![self] | T![super] | T![ident] | T![')'] if p.nth(2) != T![:] => {
|
|
||||||
// If we are in a tuple struct, then the parens following `pub`
|
|
||||||
// might be an tuple field, not part of the visibility. So in that
|
|
||||||
// case we don't want to consume an identifier.
|
|
||||||
|
|
||||||
// test pub_tuple_field
|
// test pub_parens_typepath
|
||||||
// struct MyStruct(pub (u32, u32));
|
// struct B(pub (super::A));
|
||||||
// struct MyStruct(pub (u32));
|
// struct B(pub (crate::A,));
|
||||||
// struct MyStruct(pub ());
|
T![crate] | T![self] | T![super] | T![ident] | T![')'] if p.nth(2) != T![:] => {
|
||||||
if !(in_tuple_field && matches!(p.nth(1), T![ident] | T![')'])) {
|
// If we are in a tuple struct, then the parens following `pub`
|
||||||
p.bump(T!['(']);
|
// might be an tuple field, not part of the visibility. So in that
|
||||||
paths::use_path(p);
|
// case we don't want to consume an identifier.
|
||||||
p.expect(T![')']);
|
|
||||||
}
|
// test pub_tuple_field
|
||||||
}
|
// struct MyStruct(pub (u32, u32));
|
||||||
// test crate_visibility_in
|
// struct MyStruct(pub (u32));
|
||||||
// pub(in super::A) struct S;
|
// struct MyStruct(pub ());
|
||||||
// pub(in crate) struct S;
|
if !(in_tuple_field && matches!(p.nth(1), T![ident] | T![')'])) {
|
||||||
T![in] => {
|
p.bump(T!['(']);
|
||||||
p.bump(T!['(']);
|
paths::use_path(p);
|
||||||
p.bump(T![in]);
|
p.expect(T![')']);
|
||||||
paths::use_path(p);
|
|
||||||
p.expect(T![')']);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.complete(p, VISIBILITY);
|
// test crate_visibility_in
|
||||||
true
|
// pub(in super::A) struct S;
|
||||||
}
|
// pub(in crate) struct S;
|
||||||
// test crate_keyword_vis
|
T![in] => {
|
||||||
// crate fn main() { }
|
p.bump(T!['(']);
|
||||||
// struct S { crate field: u32 }
|
p.bump(T![in]);
|
||||||
// struct T(crate u32);
|
paths::use_path(p);
|
||||||
T![crate] => {
|
p.expect(T![')']);
|
||||||
if p.nth_at(1, T![::]) {
|
|
||||||
// test crate_keyword_path
|
|
||||||
// fn foo() { crate::foo(); }
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
let m = p.start();
|
_ => {}
|
||||||
p.bump(T![crate]);
|
|
||||||
m.complete(p, VISIBILITY);
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
_ => false,
|
|
||||||
}
|
}
|
||||||
|
m.complete(p, VISIBILITY);
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opt_rename(p: &mut Parser<'_>) {
|
fn opt_rename(p: &mut Parser<'_>) {
|
||||||
|
|
|
@ -6,7 +6,6 @@ fn vis() {
|
||||||
check(PrefixEntryPoint::Vis, "fn foo() {}", "");
|
check(PrefixEntryPoint::Vis, "fn foo() {}", "");
|
||||||
check(PrefixEntryPoint::Vis, "pub(fn foo() {}", "pub");
|
check(PrefixEntryPoint::Vis, "pub(fn foo() {}", "pub");
|
||||||
check(PrefixEntryPoint::Vis, "pub(crate fn foo() {}", "pub(crate");
|
check(PrefixEntryPoint::Vis, "pub(crate fn foo() {}", "pub(crate");
|
||||||
check(PrefixEntryPoint::Vis, "crate fn foo() {}", "crate");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
SOURCE_FILE
|
|
||||||
FN
|
|
||||||
VISIBILITY
|
|
||||||
CRATE_KW "crate"
|
|
||||||
WHITESPACE " "
|
|
||||||
FN_KW "fn"
|
|
||||||
WHITESPACE " "
|
|
||||||
NAME
|
|
||||||
IDENT "main"
|
|
||||||
PARAM_LIST
|
|
||||||
L_PAREN "("
|
|
||||||
R_PAREN ")"
|
|
||||||
WHITESPACE " "
|
|
||||||
BLOCK_EXPR
|
|
||||||
STMT_LIST
|
|
||||||
L_CURLY "{"
|
|
||||||
WHITESPACE " "
|
|
||||||
R_CURLY "}"
|
|
||||||
WHITESPACE "\n"
|
|
||||||
STRUCT
|
|
||||||
STRUCT_KW "struct"
|
|
||||||
WHITESPACE " "
|
|
||||||
NAME
|
|
||||||
IDENT "S"
|
|
||||||
WHITESPACE " "
|
|
||||||
RECORD_FIELD_LIST
|
|
||||||
L_CURLY "{"
|
|
||||||
WHITESPACE " "
|
|
||||||
RECORD_FIELD
|
|
||||||
VISIBILITY
|
|
||||||
CRATE_KW "crate"
|
|
||||||
WHITESPACE " "
|
|
||||||
NAME
|
|
||||||
IDENT "field"
|
|
||||||
COLON ":"
|
|
||||||
WHITESPACE " "
|
|
||||||
PATH_TYPE
|
|
||||||
PATH
|
|
||||||
PATH_SEGMENT
|
|
||||||
NAME_REF
|
|
||||||
IDENT "u32"
|
|
||||||
WHITESPACE " "
|
|
||||||
R_CURLY "}"
|
|
||||||
WHITESPACE "\n"
|
|
||||||
STRUCT
|
|
||||||
STRUCT_KW "struct"
|
|
||||||
WHITESPACE " "
|
|
||||||
NAME
|
|
||||||
IDENT "T"
|
|
||||||
TUPLE_FIELD_LIST
|
|
||||||
L_PAREN "("
|
|
||||||
TUPLE_FIELD
|
|
||||||
VISIBILITY
|
|
||||||
CRATE_KW "crate"
|
|
||||||
WHITESPACE " "
|
|
||||||
PATH_TYPE
|
|
||||||
PATH
|
|
||||||
PATH_SEGMENT
|
|
||||||
NAME_REF
|
|
||||||
IDENT "u32"
|
|
||||||
R_PAREN ")"
|
|
||||||
SEMICOLON ";"
|
|
||||||
WHITESPACE "\n"
|
|
|
@ -1,3 +0,0 @@
|
||||||
crate fn main() { }
|
|
||||||
struct S { crate field: u32 }
|
|
||||||
struct T(crate u32);
|
|
|
@ -1,33 +0,0 @@
|
||||||
SOURCE_FILE
|
|
||||||
FN
|
|
||||||
FN_KW "fn"
|
|
||||||
WHITESPACE " "
|
|
||||||
NAME
|
|
||||||
IDENT "foo"
|
|
||||||
PARAM_LIST
|
|
||||||
L_PAREN "("
|
|
||||||
R_PAREN ")"
|
|
||||||
WHITESPACE " "
|
|
||||||
BLOCK_EXPR
|
|
||||||
STMT_LIST
|
|
||||||
L_CURLY "{"
|
|
||||||
WHITESPACE " "
|
|
||||||
EXPR_STMT
|
|
||||||
CALL_EXPR
|
|
||||||
PATH_EXPR
|
|
||||||
PATH
|
|
||||||
PATH
|
|
||||||
PATH_SEGMENT
|
|
||||||
NAME_REF
|
|
||||||
CRATE_KW "crate"
|
|
||||||
COLON2 "::"
|
|
||||||
PATH_SEGMENT
|
|
||||||
NAME_REF
|
|
||||||
IDENT "foo"
|
|
||||||
ARG_LIST
|
|
||||||
L_PAREN "("
|
|
||||||
R_PAREN ")"
|
|
||||||
SEMICOLON ";"
|
|
||||||
WHITESPACE " "
|
|
||||||
R_CURLY "}"
|
|
||||||
WHITESPACE "\n"
|
|
|
@ -1 +0,0 @@
|
||||||
fn foo() { crate::foo(); }
|
|
|
@ -145,7 +145,7 @@ pub struct PackageDependency {
|
||||||
pub kind: DepKind,
|
pub kind: DepKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum DepKind {
|
pub enum DepKind {
|
||||||
/// Available to the library, binary, and dev targets in the package (but not the build script).
|
/// Available to the library, binary, and dev targets in the package (but not the build script).
|
||||||
Normal,
|
Normal,
|
||||||
|
@ -156,23 +156,20 @@ pub enum DepKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DepKind {
|
impl DepKind {
|
||||||
fn iter(list: &[cargo_metadata::DepKindInfo]) -> impl Iterator<Item = Self> + '_ {
|
fn iter(list: &[cargo_metadata::DepKindInfo]) -> impl Iterator<Item = Self> {
|
||||||
let mut dep_kinds = Vec::new();
|
let mut dep_kinds = [None; 3];
|
||||||
if list.is_empty() {
|
if list.is_empty() {
|
||||||
dep_kinds.push(Self::Normal);
|
dep_kinds[0] = Some(Self::Normal);
|
||||||
}
|
}
|
||||||
for info in list {
|
for info in list {
|
||||||
let kind = match info.kind {
|
match info.kind {
|
||||||
cargo_metadata::DependencyKind::Normal => Self::Normal,
|
cargo_metadata::DependencyKind::Normal => dep_kinds[0] = Some(Self::Normal),
|
||||||
cargo_metadata::DependencyKind::Development => Self::Dev,
|
cargo_metadata::DependencyKind::Development => dep_kinds[1] = Some(Self::Dev),
|
||||||
cargo_metadata::DependencyKind::Build => Self::Build,
|
cargo_metadata::DependencyKind::Build => dep_kinds[2] = Some(Self::Build),
|
||||||
cargo_metadata::DependencyKind::Unknown => continue,
|
cargo_metadata::DependencyKind::Unknown => continue,
|
||||||
};
|
}
|
||||||
dep_kinds.push(kind);
|
|
||||||
}
|
}
|
||||||
dep_kinds.sort_unstable();
|
dep_kinds.into_iter().flatten()
|
||||||
dep_kinds.dedup();
|
|
||||||
dep_kinds.into_iter()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::{
|
||||||
|
|
||||||
use hir::{
|
use hir::{
|
||||||
db::{DefDatabase, ExpandDatabase, HirDatabase},
|
db::{DefDatabase, ExpandDatabase, HirDatabase},
|
||||||
Adt, AssocItem, Crate, DefWithBody, HasCrate, HasSource, HirDisplay, ModuleDef, Name,
|
Adt, AssocItem, Crate, DefWithBody, HasSource, HirDisplay, ModuleDef, Name,
|
||||||
};
|
};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
body::{BodySourceMap, SyntheticSyntax},
|
body::{BodySourceMap, SyntheticSyntax},
|
||||||
|
@ -277,7 +277,7 @@ impl flags::AnalysisStats {
|
||||||
let Err(e) = db.layout_of_adt(
|
let Err(e) = db.layout_of_adt(
|
||||||
hir_def::AdtId::from(a).into(),
|
hir_def::AdtId::from(a).into(),
|
||||||
Substitution::empty(Interner),
|
Substitution::empty(Interner),
|
||||||
a.krate(db).into(),
|
db.trait_environment(a.into()),
|
||||||
) else {
|
) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
|
@ -78,6 +78,7 @@ define_semantic_token_types![
|
||||||
(DERIVE_HELPER, "deriveHelper") => DECORATOR,
|
(DERIVE_HELPER, "deriveHelper") => DECORATOR,
|
||||||
(DOT, "dot"),
|
(DOT, "dot"),
|
||||||
(ESCAPE_SEQUENCE, "escapeSequence") => STRING,
|
(ESCAPE_SEQUENCE, "escapeSequence") => STRING,
|
||||||
|
(INVALID_ESCAPE_SEQUENCE, "invalidEscapeSequence") => STRING,
|
||||||
(FORMAT_SPECIFIER, "formatSpecifier") => STRING,
|
(FORMAT_SPECIFIER, "formatSpecifier") => STRING,
|
||||||
(GENERIC, "generic") => TYPE_PARAMETER,
|
(GENERIC, "generic") => TYPE_PARAMETER,
|
||||||
(LABEL, "label"),
|
(LABEL, "label"),
|
||||||
|
|
|
@ -640,6 +640,7 @@ fn semantic_token_type_and_modifiers(
|
||||||
HlTag::CharLiteral => semantic_tokens::CHAR,
|
HlTag::CharLiteral => semantic_tokens::CHAR,
|
||||||
HlTag::Comment => semantic_tokens::COMMENT,
|
HlTag::Comment => semantic_tokens::COMMENT,
|
||||||
HlTag::EscapeSequence => semantic_tokens::ESCAPE_SEQUENCE,
|
HlTag::EscapeSequence => semantic_tokens::ESCAPE_SEQUENCE,
|
||||||
|
HlTag::InvalidEscapeSequence => semantic_tokens::INVALID_ESCAPE_SEQUENCE,
|
||||||
HlTag::FormatSpecifier => semantic_tokens::FORMAT_SPECIFIER,
|
HlTag::FormatSpecifier => semantic_tokens::FORMAT_SPECIFIER,
|
||||||
HlTag::Keyword => semantic_tokens::KEYWORD,
|
HlTag::Keyword => semantic_tokens::KEYWORD,
|
||||||
HlTag::None => semantic_tokens::GENERIC,
|
HlTag::None => semantic_tokens::GENERIC,
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use rustc_lexer::unescape::{unescape_byte, unescape_char, unescape_literal, Mode};
|
use rustc_lexer::unescape::{
|
||||||
|
unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit, Mode,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{self, AstToken},
|
ast::{self, AstToken},
|
||||||
|
@ -146,6 +148,7 @@ impl QuoteOffsets {
|
||||||
|
|
||||||
pub trait IsString: AstToken {
|
pub trait IsString: AstToken {
|
||||||
const RAW_PREFIX: &'static str;
|
const RAW_PREFIX: &'static str;
|
||||||
|
const MODE: Mode;
|
||||||
fn is_raw(&self) -> bool {
|
fn is_raw(&self) -> bool {
|
||||||
self.text().starts_with(Self::RAW_PREFIX)
|
self.text().starts_with(Self::RAW_PREFIX)
|
||||||
}
|
}
|
||||||
|
@ -181,7 +184,7 @@ pub trait IsString: AstToken {
|
||||||
let text = &self.text()[text_range_no_quotes - start];
|
let text = &self.text()[text_range_no_quotes - start];
|
||||||
let offset = text_range_no_quotes.start() - start;
|
let offset = text_range_no_quotes.start() - start;
|
||||||
|
|
||||||
unescape_literal(text, Mode::Str, &mut |range, unescaped_char| {
|
unescape_literal(text, Self::MODE, &mut |range, unescaped_char| {
|
||||||
let text_range =
|
let text_range =
|
||||||
TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap());
|
TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap());
|
||||||
cb(text_range + offset, unescaped_char);
|
cb(text_range + offset, unescaped_char);
|
||||||
|
@ -196,6 +199,7 @@ pub trait IsString: AstToken {
|
||||||
|
|
||||||
impl IsString for ast::String {
|
impl IsString for ast::String {
|
||||||
const RAW_PREFIX: &'static str = "r";
|
const RAW_PREFIX: &'static str = "r";
|
||||||
|
const MODE: Mode = Mode::Str;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ast::String {
|
impl ast::String {
|
||||||
|
@ -213,7 +217,7 @@ impl ast::String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
let mut prev_end = 0;
|
let mut prev_end = 0;
|
||||||
let mut has_error = false;
|
let mut has_error = false;
|
||||||
unescape_literal(text, Mode::Str, &mut |char_range, unescaped_char| match (
|
unescape_literal(text, Self::MODE, &mut |char_range, unescaped_char| match (
|
||||||
unescaped_char,
|
unescaped_char,
|
||||||
buf.capacity() == 0,
|
buf.capacity() == 0,
|
||||||
) {
|
) {
|
||||||
|
@ -239,6 +243,7 @@ impl ast::String {
|
||||||
|
|
||||||
impl IsString for ast::ByteString {
|
impl IsString for ast::ByteString {
|
||||||
const RAW_PREFIX: &'static str = "br";
|
const RAW_PREFIX: &'static str = "br";
|
||||||
|
const MODE: Mode = Mode::ByteStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ast::ByteString {
|
impl ast::ByteString {
|
||||||
|
@ -256,7 +261,7 @@ impl ast::ByteString {
|
||||||
let mut buf: Vec<u8> = Vec::new();
|
let mut buf: Vec<u8> = Vec::new();
|
||||||
let mut prev_end = 0;
|
let mut prev_end = 0;
|
||||||
let mut has_error = false;
|
let mut has_error = false;
|
||||||
unescape_literal(text, Mode::ByteStr, &mut |char_range, unescaped_char| match (
|
unescape_literal(text, Self::MODE, &mut |char_range, unescaped_char| match (
|
||||||
unescaped_char,
|
unescaped_char,
|
||||||
buf.capacity() == 0,
|
buf.capacity() == 0,
|
||||||
) {
|
) {
|
||||||
|
@ -282,42 +287,70 @@ impl ast::ByteString {
|
||||||
|
|
||||||
impl IsString for ast::CString {
|
impl IsString for ast::CString {
|
||||||
const RAW_PREFIX: &'static str = "cr";
|
const RAW_PREFIX: &'static str = "cr";
|
||||||
|
const MODE: Mode = Mode::CStr;
|
||||||
|
|
||||||
|
fn escaped_char_ranges(
|
||||||
|
&self,
|
||||||
|
cb: &mut dyn FnMut(TextRange, Result<char, rustc_lexer::unescape::EscapeError>),
|
||||||
|
) {
|
||||||
|
let text_range_no_quotes = match self.text_range_between_quotes() {
|
||||||
|
Some(it) => it,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
let start = self.syntax().text_range().start();
|
||||||
|
let text = &self.text()[text_range_no_quotes - start];
|
||||||
|
let offset = text_range_no_quotes.start() - start;
|
||||||
|
|
||||||
|
unescape_c_string(text, Self::MODE, &mut |range, unescaped_char| {
|
||||||
|
let text_range =
|
||||||
|
TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap());
|
||||||
|
// XXX: This method should only be used for highlighting ranges. The unescaped
|
||||||
|
// char/byte is not used. For simplicity, we return an arbitrary placeholder char.
|
||||||
|
cb(text_range + offset, unescaped_char.map(|_| ' '));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ast::CString {
|
impl ast::CString {
|
||||||
pub fn value(&self) -> Option<Cow<'_, str>> {
|
pub fn value(&self) -> Option<Cow<'_, [u8]>> {
|
||||||
if self.is_raw() {
|
if self.is_raw() {
|
||||||
let text = self.text();
|
let text = self.text();
|
||||||
let text =
|
let text =
|
||||||
&text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
|
&text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
|
||||||
return Some(Cow::Borrowed(text));
|
return Some(Cow::Borrowed(text.as_bytes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let text = self.text();
|
let text = self.text();
|
||||||
let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
|
let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
|
||||||
|
|
||||||
let mut buf = String::new();
|
let mut buf = Vec::new();
|
||||||
let mut prev_end = 0;
|
let mut prev_end = 0;
|
||||||
let mut has_error = false;
|
let mut has_error = false;
|
||||||
unescape_literal(text, Mode::Str, &mut |char_range, unescaped_char| match (
|
let mut char_buf = [0u8; 4];
|
||||||
unescaped_char,
|
let mut extend_unit = |buf: &mut Vec<u8>, unit: CStrUnit| match unit {
|
||||||
|
CStrUnit::Byte(b) => buf.push(b),
|
||||||
|
CStrUnit::Char(c) => buf.extend(c.encode_utf8(&mut char_buf).as_bytes()),
|
||||||
|
};
|
||||||
|
unescape_c_string(text, Self::MODE, &mut |char_range, unescaped| match (
|
||||||
|
unescaped,
|
||||||
buf.capacity() == 0,
|
buf.capacity() == 0,
|
||||||
) {
|
) {
|
||||||
(Ok(c), false) => buf.push(c),
|
(Ok(u), false) => extend_unit(&mut buf, u),
|
||||||
(Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
|
(Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
|
||||||
prev_end = char_range.end
|
prev_end = char_range.end
|
||||||
}
|
}
|
||||||
(Ok(c), true) => {
|
(Ok(u), true) => {
|
||||||
buf.reserve_exact(text.len());
|
buf.reserve_exact(text.len());
|
||||||
buf.push_str(&text[..prev_end]);
|
buf.extend(text[..prev_end].as_bytes());
|
||||||
buf.push(c);
|
extend_unit(&mut buf, u);
|
||||||
}
|
}
|
||||||
(Err(_), _) => has_error = true,
|
(Err(_), _) => has_error = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
match (has_error, buf.capacity() == 0) {
|
match (has_error, buf.capacity() == 0) {
|
||||||
(true, _) => None,
|
(true, _) => None,
|
||||||
(false, true) => Some(Cow::Borrowed(text)),
|
(false, true) => Some(Cow::Borrowed(text.as_bytes())),
|
||||||
(false, false) => Some(Cow::Owned(buf)),
|
(false, false) => Some(Cow::Owned(buf)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -449,27 +449,24 @@ You'll need to close and reopen all .rs and Cargo files, or to restart the IDE,
|
||||||
Support for the language server protocol is built into Kate through the LSP plugin, which is included by default.
|
Support for the language server protocol is built into Kate through the LSP plugin, which is included by default.
|
||||||
It is preconfigured to use rust-analyzer for Rust sources since Kate 21.12.
|
It is preconfigured to use rust-analyzer for Rust sources since Kate 21.12.
|
||||||
|
|
||||||
Earlier versions allow you to use rust-analyzer through a simple settings change.
|
To change rust-analyzer config options, start from the following example and put it into Kate's "User Server Settings" tab (located under the LSP Client settings):
|
||||||
In the LSP Client settings of Kate, copy the content of the third tab "default parameters" to the second tab "server configuration".
|
|
||||||
Then in the configuration replace:
|
|
||||||
[source,json]
|
[source,json]
|
||||||
----
|
----
|
||||||
|
{
|
||||||
|
"servers": {
|
||||||
"rust": {
|
"rust": {
|
||||||
"command": ["rls"],
|
"initializationOptions": {
|
||||||
"rootIndicationFileNames": ["Cargo.lock", "Cargo.toml"],
|
"cachePriming": {
|
||||||
"url": "https://github.com/rust-lang/rls",
|
"enable": false
|
||||||
"highlightingModeRegex": "^Rust$"
|
},
|
||||||
},
|
"check": {
|
||||||
----
|
"allTargets": false
|
||||||
With
|
},
|
||||||
[source,json]
|
"checkOnSave": false
|
||||||
----
|
}
|
||||||
"rust": {
|
}
|
||||||
"command": ["rust-analyzer"],
|
}
|
||||||
"rootIndicationFileNames": ["Cargo.lock", "Cargo.toml"],
|
}
|
||||||
"url": "https://github.com/rust-lang/rust-analyzer",
|
|
||||||
"highlightingModeRegex": "^Rust$"
|
|
||||||
},
|
|
||||||
----
|
----
|
||||||
Then click on apply, and restart the LSP server for your rust project.
|
Then click on apply, and restart the LSP server for your rust project.
|
||||||
|
|
||||||
|
|
|
@ -35,9 +35,12 @@
|
||||||
"build-base": "esbuild ./src/main.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node --target=node16",
|
"build-base": "esbuild ./src/main.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node --target=node16",
|
||||||
"build": "npm run build-base -- --sourcemap",
|
"build": "npm run build-base -- --sourcemap",
|
||||||
"watch": "npm run build-base -- --sourcemap --watch",
|
"watch": "npm run build-base -- --sourcemap --watch",
|
||||||
"lint": "prettier --check . && eslint -c .eslintrc.js --ext ts ./src ./tests",
|
"format": "prettier --write .",
|
||||||
"fix": "prettier --write . && eslint -c .eslintrc.js --ext ts ./src ./tests --fix",
|
"format:check": "prettier --check .",
|
||||||
"pretest": "tsc && npm run build",
|
"lint": "eslint -c .eslintrc.js --ext ts ./src ./tests",
|
||||||
|
"lint:fix": "npm run lint -- --fix",
|
||||||
|
"typecheck": "tsc",
|
||||||
|
"pretest": "npm run typecheck && npm run build",
|
||||||
"test": "node ./out/tests/runTests.js"
|
"test": "node ./out/tests/runTests.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1801,12 +1804,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "escapeSequence",
|
"id": "escapeSequence",
|
||||||
"description": "Style for char escapes in strings"
|
"description": "Style for char or byte escapes in strings"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "formatSpecifier",
|
"id": "formatSpecifier",
|
||||||
"description": "Style for {} placeholders in format strings"
|
"description": "Style for {} placeholders in format strings"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "invalidEscapeSequence",
|
||||||
|
"description": "Style for invalid char or byte escapes in strings"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "label",
|
"id": "label",
|
||||||
"description": "Style for labels"
|
"description": "Style for labels"
|
||||||
|
|
|
@ -66,6 +66,12 @@ export async function startDebugSession(ctx: Ctx, runnable: ra.Runnable): Promis
|
||||||
return vscode.debug.startDebugging(undefined, debugConfig);
|
return vscode.debug.startDebugging(undefined, debugConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createCommandLink(extensionId: string): string {
|
||||||
|
// do not remove the second quotes inside
|
||||||
|
// encodeURIComponent or it won't work
|
||||||
|
return `extension.open?${encodeURIComponent(`"${extensionId}"`)}`;
|
||||||
|
}
|
||||||
|
|
||||||
async function getDebugConfiguration(
|
async function getDebugConfiguration(
|
||||||
ctx: Ctx,
|
ctx: Ctx,
|
||||||
runnable: ra.Runnable,
|
runnable: ra.Runnable,
|
||||||
|
@ -90,9 +96,12 @@ async function getDebugConfiguration(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!debugEngine) {
|
if (!debugEngine) {
|
||||||
|
const commandCodeLLDB: string = createCommandLink("vadimcn.vscode-lldb");
|
||||||
|
const commandCpp: string = createCommandLink("ms-vscode.cpptools");
|
||||||
|
|
||||||
await vscode.window.showErrorMessage(
|
await vscode.window.showErrorMessage(
|
||||||
`Install [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)` +
|
`Install [CodeLLDB](command:${commandCodeLLDB} "Open CodeLLDB")` +
|
||||||
` or [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) extension for debugging.`,
|
` or [C/C++](command:${commandCpp} "Open C/C++") extension for debugging.`,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue