Skip to content

Commit 26242c0

Browse files
authored
Merge pull request #441 from Mcat12/feature/str-typename
Add the str type
2 parents adec469 + 5e763a3 commit 26242c0

File tree

12 files changed

+83
-14
lines changed

12 files changed

+83
-14
lines changed

book/src/clauses/well_known_traits.md

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Some common examples of auto traits are `Send` and `Sync`.
3333
| tuple types ||||||||||
3434
| structs ||||||||||
3535
| scalar types | 📚 | 📚 ||||||||
36+
| str | 📚 | 📚 ||||||||
3637
| trait objects ||||||||||
3738
| functions ptrs ||||||||||
3839
| raw ptrs ||||||||||

chalk-integration/src/lowering.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,7 @@ impl LowerProjectionTy for ProjectionTy {
10851085
}
10861086

10871087
trait LowerTy {
1088+
/// Lower from the AST to Chalk's Rust IR
10881089
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::Ty<ChalkIr>>;
10891090
}
10901091

@@ -1257,6 +1258,12 @@ impl LowerTy for Ty {
12571258
),
12581259
})
12591260
.intern(interner)),
1261+
1262+
Ty::Str => Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy {
1263+
name: chalk_ir::TypeName::Str,
1264+
substitution: chalk_ir::Substitution::empty(interner),
1265+
})
1266+
.intern(interner)),
12601267
}
12611268
}
12621269
}

chalk-ir/src/debug.rs

+1
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ impl<I: Interner> Debug for TypeName<I> {
142142
TypeName::Struct(id) => write!(fmt, "{:?}", id),
143143
TypeName::AssociatedType(assoc_ty) => write!(fmt, "{:?}", assoc_ty),
144144
TypeName::Scalar(scalar) => write!(fmt, "{:?}", scalar),
145+
TypeName::Str => write!(fmt, "Str"),
145146
TypeName::Tuple(arity) => write!(fmt, "{:?}", arity),
146147
TypeName::OpaqueType(opaque_ty) => write!(fmt, "!{:?}", opaque_ty),
147148
TypeName::Slice => write!(fmt, "{{slice}}"),

chalk-ir/src/lib.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ pub enum TypeName<I: Interner> {
168168
/// a placeholder for opaque types like `impl Trait`
169169
OpaqueType(OpaqueTyId<I>),
170170

171+
/// the string primitive type
172+
Str,
173+
171174
/// This can be used to represent an error, e.g. during name resolution of a type.
172175
/// Chalk itself will not produce this, just pass it through when given.
173176
Error,
@@ -966,7 +969,7 @@ pub enum WhereClause<I: Interner> {
966969

967970
#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner, Zip)]
968971
pub enum WellFormed<I: Interner> {
969-
/// A predicate which is true is some trait ref is well-formed.
972+
/// A predicate which is true when some trait ref is well-formed.
970973
/// For example, given the following trait definitions:
971974
///
972975
/// ```notrust
@@ -981,7 +984,7 @@ pub enum WellFormed<I: Interner> {
981984
/// ```
982985
Trait(TraitRef<I>),
983986

984-
/// A predicate which is true is some type is well-formed.
987+
/// A predicate which is true when some type is well-formed.
985988
/// For example, given the following type definition:
986989
///
987990
/// ```notrust

chalk-parse/src/ast.rs

+1
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ pub enum Ty {
206206
lifetime: Lifetime,
207207
ty: Box<Ty>,
208208
},
209+
Str,
209210
}
210211

211212
#[derive(Copy, Clone, PartialEq, Eq, Debug)]

chalk-parse/src/parser.lalrpop

+1
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ pub Ty: Ty = {
196196

197197
TyWithoutFor: Ty = {
198198
<ScalarType> => Ty::Scalar { ty: <> },
199+
"str" => Ty::Str,
199200
<n:Id> => Ty::Id { name: n},
200201
"fn" "(" <t:Ty> ")" => Ty::ForAll {
201202
lifetime_names: vec![],

chalk-solve/src/clauses.rs

+2
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ fn match_ty<I: Interner>(
389389
})
390390
}
391391

392+
/// Lower a Rust IR application type to logic
392393
fn match_type_name<I: Interner>(
393394
builder: &mut ClauseBuilder<'_, I>,
394395
interner: &I,
@@ -408,6 +409,7 @@ fn match_type_name<I: Interner>(
408409
TypeName::Scalar(_) => {
409410
builder.push_fact(WellFormed::Ty(application.clone().intern(interner)))
410411
}
412+
TypeName::Str => builder.push_fact(WellFormed::Ty(application.clone().intern(interner))),
411413
TypeName::Tuple(_) => {
412414
builder.push_fact(WellFormed::Ty(application.clone().intern(interner)))
413415
}

tests/lowering/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ fn slices() {
555555
}
556556

557557
error_msg {
558-
"parse error: UnrecognizedToken { token: (29, Token(31, \"]\"), 30), expected: [\"\\\"&\\\"\", \"\\\"(\\\"\", \"\\\"*\\\"\", \"\\\"<\\\"\", \"\\\"[\\\"\", \"\\\"bool\\\"\", \"\\\"char\\\"\", \"\\\"dyn\\\"\", \"\\\"f32\\\"\", \"\\\"f64\\\"\", \"\\\"fn\\\"\", \"\\\"for\\\"\", \"\\\"i128\\\"\", \"\\\"i16\\\"\", \"\\\"i32\\\"\", \"\\\"i64\\\"\", \"\\\"i8\\\"\", \"\\\"isize\\\"\", \"\\\"u128\\\"\", \"\\\"u16\\\"\", \"\\\"u32\\\"\", \"\\\"u64\\\"\", \"\\\"u8\\\"\", \"\\\"usize\\\"\", \"r#\\\"([A-Za-z]|_)([A-Za-z0-9]|_)*\\\"#\"] }"
558+
"parse error: UnrecognizedToken { token: (29, Token(31, \"]\"), 30), expected: [\"\\\"&\\\"\", \"\\\"(\\\"\", \"\\\"*\\\"\", \"\\\"<\\\"\", \"\\\"[\\\"\", \"\\\"bool\\\"\", \"\\\"char\\\"\", \"\\\"dyn\\\"\", \"\\\"f32\\\"\", \"\\\"f64\\\"\", \"\\\"fn\\\"\", \"\\\"for\\\"\", \"\\\"i128\\\"\", \"\\\"i16\\\"\", \"\\\"i32\\\"\", \"\\\"i64\\\"\", \"\\\"i8\\\"\", \"\\\"isize\\\"\", \"\\\"str\\\"\", \"\\\"u128\\\"\", \"\\\"u16\\\"\", \"\\\"u32\\\"\", \"\\\"u64\\\"\", \"\\\"u8\\\"\", \"\\\"usize\\\"\", \"r#\\\"([A-Za-z]|_)([A-Za-z0-9]|_)*\\\"#\"] }"
559559
}
560560
}
561561
}

tests/test/coherence.rs

+9-10
Original file line numberDiff line numberDiff line change
@@ -257,31 +257,30 @@ fn downstream_impl_of_fundamental_43355() {
257257

258258
#[test]
259259
fn fundamental_traits() {
260-
// We want to enable negative reasoning about some traits. For example, consider the str type.
261-
// We know that str is never going to be Sized and we have made a decision to allow people to
262-
// depend on that. The following two impls are rejected as overlapping despite the fact that we
263-
// know that str will never be Sized.
260+
// We want to enable negative reasoning about some traits. For example, assume we have some
261+
// "Foo" type which we know is never going to be Sized (ex. str). The following two impls are
262+
// rejected as overlapping despite the fact that we know that Foo will never be Sized.
264263
lowering_error! {
265264
program {
266265
#[upstream] trait Sized { }
267-
#[upstream] struct str { }
266+
#[upstream] struct Foo { }
268267
trait Bar { }
269-
impl Bar for str { }
268+
impl Bar for Foo { }
270269
impl<T> Bar for T where T: Sized { }
271270
} error_msg {
272271
"overlapping impls of trait `Bar`"
273272
}
274273
}
275274

276275
// If we make Sized fundamental, we're telling the Rust compiler that it can reason negatively
277-
// about it. That means that `not { str: Sized }` is provable. With that change, these two
278-
// impls are now valid.
276+
// about it. That means that `not { Foo: Sized }` is provable. With that change, these two impls
277+
// are now valid.
279278
lowering_success! {
280279
program {
281280
#[upstream] #[fundamental] trait Sized { }
282-
#[upstream] struct str { }
281+
#[upstream] struct Foo { }
283282
trait Bar { }
284-
impl Bar for str { }
283+
impl Bar for Foo { }
285284
impl<T> Bar for T where T: Sized { }
286285
}
287286
}

tests/test/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ mod projection;
318318
mod refs;
319319
mod scalars;
320320
mod slices;
321+
mod string;
321322
mod tuples;
322323
mod unify;
323324
mod wf_goals;

tests/test/string.rs

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use super::*;
2+
3+
#[test]
4+
fn str_trait_impl() {
5+
test! {
6+
program {
7+
trait Foo {}
8+
impl Foo for str {}
9+
}
10+
11+
goal { str: Foo } yields { "Unique" }
12+
}
13+
}
14+
15+
#[test]
16+
fn str_is_well_formed() {
17+
test! {
18+
program {}
19+
goal { WellFormed(str) } yields { "Unique" }
20+
}
21+
}
22+
23+
#[test]
24+
fn str_is_not_sized() {
25+
test! {
26+
program {
27+
#[lang(sized)] trait Sized {}
28+
}
29+
30+
goal { not { str: Sized } } yields { "Unique" }
31+
}
32+
}
33+
34+
#[test]
35+
fn str_is_not_copy() {
36+
test! {
37+
program {
38+
#[lang(copy)] trait Copy {}
39+
}
40+
41+
goal { not { str: Copy } } yields { "Unique" }
42+
}
43+
}
44+
45+
#[test]
46+
fn str_is_not_clone() {
47+
test! {
48+
program {
49+
#[lang(clone)] trait Clone {}
50+
}
51+
52+
goal { not { str: Clone } } yields { "Unique" }
53+
}
54+
}

tests/test/wf_lowering.rs

-1
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,6 @@ fn assoc_type_recursive_bound() {
576576
}
577577

578578
struct Number { }
579-
struct str { } // not sized
580579

581580
impl Foo for Number {
582581
// Well-formedness checks require that the following

0 commit comments

Comments
 (0)