Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions pyrefly/lib/report/glean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,28 @@ class Outer:
totals = [n * 2 for n in range(3)]
"#;

let string_literal = r#"from enum import StrEnum
from typing import Literal, LiteralString

def plain(word: str) -> str:
return word.title()

def literal(word: Literal["red"]) -> str:
return word.title()

def literal_string(word: LiteralString) -> str:
return word.title()

def joined(parts: list[str]) -> str:
return ", ".join(parts)

class Colour(StrEnum):
RED = "red"

def label(self) -> str:
return self.value.title()
"#;

let files = [
("simple", simple_code),
("classes", classes_code),
Expand All @@ -307,6 +329,7 @@ totals = [n * 2 for n in range(3)]
("inherited_members", inherited_members),
("nested_later_class", nested_later_class),
("comprehensions", comprehensions),
("string_literal", string_literal),
];
let (handles, state) = mk_multi_file_state_assert_no_errors(&files, Require::Everything);
let transaction = state.transaction();
Expand Down
19 changes: 15 additions & 4 deletions pyrefly/lib/report/glean/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1002,11 +1002,22 @@ impl GleanState<'_> {
let completions = |ty| solver.completions(ty, Some(attr_name), false, false);
// The class that defines `attr_name`, as found by the solver's own member
// lookup, so that an inherited member is named after its defining class.
let defining_type = |ty: Type| match &ty {
Type::ClassType(cls) | Type::SelfType(cls) => solver
let defining_type = |ty: Type| {
// A literal is an instance of its general class (e.g. `"a"` is a `str`),
// so its members are named after that class.
let cls = match &ty {
Type::ClassType(cls) | Type::SelfType(cls) => cls.clone(),
Type::Literal(lit) => {
lit.value.general_class_type(solver.stdlib).clone()
}
Type::LiteralString(_) => solver.stdlib.str().clone(),
_ => return ty,
};
solver
.get_class_member_with_defining_class(cls.class_object(), attr_name)
.map_or(ty.clone(), |member| Type::ClassDef(member.defining_class)),
_ => ty,
.map_or(Type::ClassType(cls), |member| {
Type::ClassDef(member.defining_class)
})
};

let tys = match base_type.clone() {
Expand Down
Loading
Loading